气泡排序无限循环错误的变化

问题描述 投票:0回答:1

在特定的棋盘游戏中,恰好有一行,它包含N个空格,从左到右从0到N-1编号。还有N颗大理石,编号从0到N-1,最初以任意顺序放置。之后,有两个可用的动作,一次只能执行一次:

  • 切换:将弹珠切换到位置0和1。
  • 旋转:移动大理石从位置0移至位置N-1,然后移动所有其他大理石左边一个空格(低一个索引)。

目标是按顺序排列大理石,每个大理石i都位于位置i。

我编写的代码适用于问题所在的示例(1 3 0 2),但是当我将额外的数字4随机添加到列表中时,while循环永远不会终止。查看排序后的序列,似乎会反复遍历多个相同序列。我不确定为什么它适用于一个系列而不适用于下一个系列。

奖金,我似乎无法弄清楚如何将输出结果打印为以空格分隔的数字,而不是带有方括号和逗号的列表。问题要求我们将输出打印为以空格分隔的数字。任何帮助,将不胜感激。

class MarblesBoard:
    """creates a marble board with number marbles in specific spots"""
    def __init__(self, marble_sequence):
        self.board = [x for x in marble_sequence]

    def __str__(self):
        return str(self.board)

    def __repr__(self):
        return "%r " % (self.board)

    def switch(self):
        """switch the marbles in position 0 and 1"""
        self.board[0], self.board[1] = self.board[1], self.board[0]
        return self.board

    def rotate(self):
        """Move the marble in position 0 to position N - 1, and move all other marbles one space to the left (one index lower)"""
        copy_board = self.board.copy()
        copy_board[len(self.board)-1] = self.board[0]
        for x in range(1, len(self.board)):
            copy_board[x - 1] = self.board[x]
        self.board = copy_board
        return self.board

    def is_sorted(self):
        return self.board == sorted(self.board):

class Solver:
    """solves the marble sorting game when given a marble board as input"""

    def __init__(self, MarblesBoard):
        self.steps = 0
        self.board = MarblesBoard.board
        return

    def solve(self):
        n = len(self.board)
        # print("n = ", n)
        print(self.board)
        while MarblesBoard.is_sorted(self) == False:
            if self.board[0] > self.board[1]:
                MarblesBoard.rotate(self)
                print(self.board)
                self.steps += 1
            else:
                MarblesBoard.switch(self)
                print(self.board)
                self.steps += 1
        print("total steps: ", self.steps)

关于输出,代码对于此处的示例输出正常工作:

board2 = MarblesBoard((1,3,0,2))
solver = Solver(board2)
solver.solve()

[1, 3, 0, 2]
[3, 1, 0, 2]
[1, 0, 2, 3]
[0, 2, 3, 1]
[2, 0, 3, 1]
[0, 3, 1, 2]
[3, 0, 1, 2]
[0, 1, 2, 3]
total steps:  7

但是,如果我在起始板上添加4:

board2 = MarblesBoard((1,3,0,2,4))
solver = Solver(board2)
solver.solve()

[1, 3, 0, 2, 4]
[3, 1, 0, 2, 4]
[1, 0, 2, 4, 3]
[0, 2, 4, 3, 1]
[2, 0, 4, 3, 1]
[0, 4, 3, 1, 2]
[4, 0, 3, 1, 2]
[0, 3, 1, 2, 4]
[3, 0, 1, 2, 4]
[0, 1, 2, 4, 3]
[1, 0, 2, 4, 3]
[0, 2, 4, 3, 1]
[2, 0, 4, 3, 1]
[0, 4, 3, 1, 2]
[4, 0, 3, 1, 2]
[0, 3, 1, 2, 4]
[3, 0, 1, 2, 4]

请注意,3 0 1 2 4重复作为第二次迭代和最后列出的迭代。由于while循环的结构,由于发生了相同的序列,因此实现了相同的步骤,并且循环无限地继续。

python while-loop bubble-sort
1个回答
0
投票

所以,它到底是冒泡排序的一种变体?大多数排序都可以将已排序和未排序的数据保存在单独的区域中,以便清楚地对已排序的数据进行排序。这种排序似乎没有做到。

看来,发生切换的唯一标准是当board[0] > board[1]时。那真的是全部吗?

我对代码的建议如下:

class MarblesBoard:

    def __init__(self, marble_sequence):
        self.board = [x for x in marble_sequence]

不是有点多余吗?为什么不:

class MarblesBoard:

    def __init__(self, marble_sequence):
        self.board = marble_sequence

我似乎无法弄清楚如何将输出打印为数字用空格隔开

这使我进入了__str__的实现:

def __str__(self):
        return str(self.board)

不会。看看在外壳中尝试执行类似操作时返回的字符串:

>>> str([1, 2, 3])
'[1, 2, 3]'
>>> 

最好使用str.join

def __str__(self):
    return " ".join(map(str, self.board))

您的switch方法看起来不错,但您不需要从中返回任何东西。只需交换元素,这就是您要做的全部。

如果我正确理解了rotate方法,则可以简化它:

def rotate(self):
    self.board.append(self.board.pop(0))

同样,您不需要从此函数返回任何内容。

您的is_sorted也可以简化:

def is_sorted(self):
    return self.board == sorted(self.board)

我可能还会在您的should_rotate类中添加一个名为MarblesBoard的方法,该方法根据求解器是否应该旋转或切换来返回TrueFalse。它打算稍后供求解器使用:

def should_rotate(self):
    return self.board[0] > self.board[1]

接下来是Solver类。首先__init__方法:

通过命名参数MarblesBoard(与该类相同的名称),您正在遮盖该类的标识符-因此,我不会将其称为该参数。我认为marbles_board是更好的名称。

[第二,我看不出在steps中明确地将__init__设置为实例变量的充分理由,因为您使用它的唯一位置是solve方法。我现在暂时摆脱它。

[第三,我认为将self.board绑定到board实例的MarblesBoard对象不是一个好主意。如果您的Solver类基本上只是包装一个MarblesBoard.board,那么您甚至不制作此类,而只需在MarblesBoard类中进行所有求解即可。同样,您无需从return中显式显示__init__

class Solver:

    def __init__(self, marbles_board):
        self.marbles_board = marbles_board

solve也可以简化一点:

def solve(self):

    number_of_steps = 0

    while not self.marbles_board.is_sorted():
        if self.marbles_board.should_rotate():
            self.marbles_board.rotate()
        else:
            self.marbles_board.switch()
        number_of_steps += 1
    print(f"Number of steps: {number_of_steps}")

[您对solve的实现工作得很好,这很有趣,看到您如何将selfSolver对象)作为rotateswitch方法的参数传入。

© www.soinside.com 2019 - 2024. All rights reserved.