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

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

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