VB.NET 自定义复杂排序的最少步骤

我也想说,我不在乎算法生成的哪种解决方案,因为我知道对于相同数量的移动有很多解决方案。

我只想要当前谜题的最少移动的任何解决方案。

谢谢你。我实在想不出有什么模式,我只知道最小的数字必须放在前面,最大的数字必须放在后面,但诀窍是它一次移动两个数字,一个从前面,一个从后面,就像一起使用更可修改的堆栈进行排序一样。

这个游戏只有2种移动..

  • 在任何偏移量处进行左循环旋转(除了最后一个字节)右
  • 在任何偏移量处进行循环旋转(除了最后一个字节)

这是该功能的代码

Public Function CyclicRotationOffset(ByVal data() As Byte, ByVal beginOffset As Integer, ByVal leftDirection As Boolean) As Byte()    'Left Direction = true    '--------------------------------------------------------    'Shifted cyclically rotation If [a, b, c] then [b, c, a]    '--------------------------------------------------------    'Left Direction = false    '--------------------------------------------------------    'Shifted cyclically rotation If [a, b, c] then [c, a, b]    '--------------------------------------------------------    If beginOffset = UBound(data) Then        'last byte cannot do anything.        Return data    End If    Dim newdata() As Byte    ReDim newdata(UBound(data))    If leftDirection = True Then        newdata(UBound(newdata)) = data(beginOffset) '1st element will be last.        For i = beginOffset To UBound(data) - 1            newdata(i) = data(i + 1)        Next i    Else        newdata(beginOffset) = data(UBound(data)) 'last element will be first.        For i = beginOffset + 1 To UBound(data)            newdata(i) = data(i - 1)        Next i    End If    If beginOffset > 0 Then        Buffer.BlockCopy(data, 0, newdata, 0, beginOffset)    End If    Return newdataEnd Function

这里有两个例子
———————————————-
数据,在6次移动中解决(使用蛮力和函数)。
2, 7, 3, 1, 6, 4, 5, 8, 9
———————————————-
蛮力旋转
3次左,3次右
———————————————-
1, 左
2, 左
0, 右
6, 右
3, 左
5, 右
———————————————
2, 3, 1, 6, 4, 5, 8, 9, 7
2, 3, 6, 4, 5, 8, 9, 7, 1
1, 2, 3, 6, 4, 5, 8, 9, 7
1, 2, 3, 6, 4, 5, 7, 8, 9
1, 2, 3, 4, 5, 7, 8, 9, 6
1, 2, 3, 4, 5, 6, 7, 8, 9 <- 最终一个产生排序答案
———————————————-

这里是一个更难的例子(这个难倒了我)
在7次移动中解决(使用蛮力)
数据=
3, 9, 7, 4, 2, 5, 1, 6, 8
答案=
1, 2, 3, 4, 5, 6, 7, 8, 9

4次左,3次右
移动步骤
6, 左
0, 右
3, 左
7, 右
2, 左
3, 左
1, 右

3, 9, 7, 4, 2, 5, 6, 8, 1
1, 3, 9, 7, 4, 2, 5, 6, 8
1, 3, 9, 4, 2, 5, 6, 8, 7
1, 3, 9, 4, 2, 5, 6, 7, 8
1, 3, 4, 2, 5, 6, 7, 8, 9
1, 3, 4, 5, 6, 7, 8, 9, 2
1, 2, 3, 4, 5, 6, 7, 8, 9

这是我找到第一个谜题6次移动解决方案的代码,但对于第二个谜题,它处理得不对,所以解决方案需要14次移动而不是最优的7次移动

Public Structure OffsetMove    Dim moveId As Byte    Dim randomOffset As Byte    Public Sub New(ByVal moveId As Byte, ByVal randomOffset As Byte)        Me.moveId = moveId        Me.randomOffset = randomOffset    End SubEnd StructurePublic Function SortDataCyclic(ByVal data() As Byte) As List(Of OffsetMove)    Dim answer() As Byte    ReDim answer(UBound(data))    Buffer.BlockCopy(data, 0, answer, 0, data.Length)    Array.Sort(answer)    Dim newdata() As Byte    ReDim newdata(UBound(data))    Buffer.BlockCopy(data, 0, newdata, 0, data.Length)    Dim i As Long = 0    Dim j As Long = 0    Dim k As Long = 0    Dim l As Long = 0    Dim solutionCount As Integer = 0    Dim movesTaken As New List(Of OffsetMove)    Debug.Print("---------------------------------------------")    Dim sortedPairs As New List(Of Byte)    While j < 8        If sortedPairs.Count >= 3 Then            'Insertion right cyclic rotations go here            While l < 9                k = 0                While k < 9                    If newdata(k) > newdata(8) Then Exit While                    k += 1                End While                If k = 9 Then                    'fully sorted already, nothing left to insert.                    Exit While                End If                newdata = CyclicRotationOffset(newdata, k, False)                movesTaken.Add(New OffsetMove(1, k))                printDebug(newdata)                l += 1            End While            'Exit the while, everything is sorted.            Exit While            '1, 2, x, x, x, x        ElseIf j + 1 < 9 AndAlso _            newdata(j + 1) = (newdata(j) + 1) Then            sortedPairs.Add(j)            j += 2            '1, x, 2, x, x, x        ElseIf j + 2 < 9 AndAlso _            newdata(j + 2) = (newdata(j) + 1) Then            newdata = CyclicRotationOffset(newdata, (j + 1), True)            movesTaken.Add(New OffsetMove(0, (j + 1)))            printDebug(newdata)            j = 0            'No pair pattern at all.        Else            newdata = CyclicRotationOffset(newdata, j, True)            movesTaken.Add(New OffsetMove(0, j))            printDebug(newdata)        End If    End While    Return movesTakenEnd FunctionPublic Sub printDebug(ByVal data() As Byte)    Debug.Print(data(0) & ", " & data(1) & ", " & data(2) & ", " & data(3) & ", " & data(4) & ", " & data(5) & ", " & data(6) & ", " & data(7) & ", " & data(8))End Sub

回答:

我使用了你的代码,得到了与你不同的结果集。我认为部分原因在于你在while循环中对sortedPairs.Count的逻辑处理。我也对i、j、k和l之间的区别感到困惑。所以我使用了一些稍微不同的逻辑重写了你的While循环。

    Dim currentNumber As Integer = 1    Dim currentPositionOfNumber As Integer = 0    While currentNumber - 1 < 8        currentPositionOfNumber = GetIndexOfNumber(newdata, currentNumber)        If currentNumber - 1 = currentPositionOfNumber Then            'do nothing        ElseIf currentNumber = currentPositionOfNumber Then            '如果需要移动的数字在它需要的位置的直接右侧,那么只需向左旋转一次            newdata = CyclicRotationOffset(newdata, currentNumber - 1, True)            movesTaken.Add(New OffsetMove(1, k))            printDebug(newdata)        ElseIf currentPositionOfNumber = 8 Then            '如果需要移动的数字在最后一个位置,则旋转到正确的位置            newdata = CyclicRotationOffset(newdata, currentNumber - 1, False)            movesTaken.Add(New OffsetMove(1, k))            printDebug(newdata)        ElseIf currentNumber = newdata(currentPositionOfNumber + 1) - 1 Then            '如果数字不在上述任何位置,但它右侧的数字是下一个更高的数字,那么只需向左旋转直到这对数字在正确的位置            Do Until GetIndexOfNumber(newdata, currentNumber) = currentNumber - 1                newdata = CyclicRotationOffset(newdata, currentNumber - 1, True)                movesTaken.Add(New OffsetMove(1, k))                printDebug(newdata)            Loop        Else            '向左旋转一次,然后向右旋转到正确的位置            newdata = CyclicRotationOffset(newdata, currentPositionOfNumber, True)            movesTaken.Add(New OffsetMove(1, k))            printDebug(newdata)            newdata = CyclicRotationOffset(newdata, currentNumber - 1, False)            movesTaken.Add(New OffsetMove(1, k))            printDebug(newdata)        End If        currentNumber += 1    End While

我还有一个函数来查找当前正在评估的数字在数组中的位置

Public Function GetIndexOfNumber(data() As Byte, number As Integer) As Integer    For i = 0 To 8        If data(i) = number Then Return i    NextEnd Function

有了这个,我得到了以下结果…测试1 = 6次移动测试2 = 7次移动

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注