在特定的棋盘游戏中,恰好有一行,它包含N个空格,从左到右从0到N-1编号。还有N颗大理石,编号从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循环的结构,由于发生了相同的序列,因此实现了相同的步骤,并且循环无限地继续。
所以,它到底是冒泡排序的一种变体?大多数排序都可以将已排序和未排序的数据保存在单独的区域中,以便清楚地对已排序的数据进行排序。这种排序似乎没有做到。
看来,发生切换的唯一标准是当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
的方法,该方法根据求解器是否应该旋转或切换来返回True
或False
。它打算稍后供求解器使用:
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
的实现工作得很好,这很有趣,看到您如何将self
(Solver
对象)作为rotate
和switch
方法的参数传入。