簡體   English   中英

冒泡排序無限循環錯誤的變化

[英]Variation on Bubble Sort infinite loop error

在一個特定的棋盤游戲中,只有一行,它包含 N 個空格,從左到右編號為 0 到 N - 1。 還有 N 個彈珠,編號從 0 到 N - 1,最初以任意順序放置。 之后,有兩個可用的動作,一次只能做一個:

  • 切換:切換位置 0 和 1 的彈珠。
  • 旋轉:將 position 0 中的彈珠移動到 position N - 1,並將所有其他彈珠向左移動一格(下一個索引)。

目標是按順序排列彈珠,每個彈珠 i 在 position i 中。

我編寫的代碼適用於發布在問題上的示例(1 3 0 2),但是當我將額外的數字 4 隨機添加到列表中時,while 循環永遠不會終止。 查看排序后的序列,它似乎在重復循環多個相同的序列。 我不確定為什么它適用於一個系列但不適用於下一個系列。

獎勵,我似乎無法弄清楚如何將 output 打印為用空格分隔的數字與用括號和逗號分隔的列表。 問題要求我們將 output 打印為以空格分隔的數字。 對此的任何幫助將不勝感激。

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)

關於 output,代碼在此處適用於示例 output:

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 循環的結構,由於發生相同的序列,因此執行相同的步驟並且循環無限繼續。

那么,冒泡排序究竟是如何變化的呢? 大多數排序都有一種方法將已排序和未排序的數據保存在不同的區域中,以便清楚已經排序的數據。 這種似乎並沒有做到這一點。

看起來切換發生的唯一標准是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

我似乎無法弄清楚如何將 output 打印為用空格分隔的數字

這將我帶到您對__str__的實施:

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

那不行。 看看我嘗試在 shell 中執行類似操作時返回的字符串:

>>> 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))

同樣,您不需要從此 function 返回任何內容。

您的is_sorted也可以簡化:

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

我也可能會在您的MarblesBoard class 中添加一個名為should_rotate的方法,該方法根據求解器是否應該旋轉或切換返回TrueFalse 它打算稍后由求解器使用:

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

接下來, Solver class。 首先是__init__方法:

通過命名參數MarblesBoard (與類同名),您將隱藏 class 的標識符 - 所以我不會調用該參數。 我認為marbles_board是一個更好的名字。

其次,我認為沒有充分的理由在您的__init__中明確地將steps設置為實例變量,因為您使用它的唯一地方是在solve方法中。 我現在就擺脫它。

第三,我認為將self.board綁定到MarblesBoard實例的board object 不是一個好主意。 如果您的Solver class 基本上只是環繞MarblesBoard.board ,那么您甚至可能不做這個 class 並在MarblesBoard class 中完成所有求解同樣,您不需要從__init__顯式return

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方法的參數傳遞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM