河内塔与Python,使用列表打印每个步骤。但我不想使用全局变量



代码说明:输入n是整数,其他输入是list(降序(。 例如,n=3A=list(range(n,0,-1))B=[]C=[](较大的整数表示较大的圆盘(。

输入列表变量(start_inter_end_(名称必须ABC因为河内函数包括全局变量ABC。这是一件烦人的事情。

如何在没有全局变量的情况下用列表表示每个步骤?换句话说,基本情况的操作(追加、删除(如何取决于输入位置而不是变量名称。

例如:

start_是第二个输入变量,end_是第四个输入变量。

基本情况操作 -> 第四个输入变量.append(第二个输入变量[-1], 第二个输入变量。删除(第二个输入变量[-1](

def Hanoi(n,start_,inter_,end_):
if n==1:
end_.append(start_[-1])
start_.remove(start_[-1])
print('start_peg , inter_peg, end_peg :{}t{}t{}'.format(A,B,C))
else:
Hanoi(n-1,start_,end_,inter_)
Hanoi(1,start_,inter_,end_)
Hanoi(n-1,inter_,start_,end_)
n=3
A=list(range(n,0,-1))
B,C=[],[]
Hanoi(n,A,B,C) #variable name of three list input must be A,B,C

Out:
start_peg , inter_peg, end_peg :[3, 2]  []      [1]
start_peg , inter_peg, end_peg :[3]     [2]     [1]
start_peg , inter_peg, end_peg :[3]     [2, 1]  []
start_peg , inter_peg, end_peg :[]      [2, 1]  [3]
start_peg , inter_peg, end_peg :[1]     [2]     [3]
start_peg , inter_peg, end_peg :[1]     []      [3, 2]
start_peg , inter_peg, end_peg :[]      []      [3, 2, 1]

第五行----中---- (start_,inter_,end_(而不是(A,B,C(

def Hanoi(n,start_,inter_,end_):
if n==1:
end_.append(start_[-1])
start_.remove(start_[-1])
print('start_peg , inter_peg, end_peg :{}t{}t{}'.format(start_,inter_,end_))
else:
Hanoi(n-1,start_,end_,inter_)
Hanoi(1,start_,inter_,end_)
Hanoi(n-1,inter_,start_,end_)
# it's possible to use any input variable name
n=3
a=list(range(n,0,-1))
b,c=[],[]
Hanoi(n,a,b,c)
Out:
start_peg , inter_peg, end_peg :[3, 2]  []      [1]
start_peg , inter_peg, end_peg :[3]     [1]     [2]
start_peg , inter_peg, end_peg :[]      [3]     [2, 1]
start_peg , inter_peg, end_peg :[]      [2, 1]  [3]
start_peg , inter_peg, end_peg :[2]     [3]     [1]
start_peg , inter_peg, end_peg :[]      [1]     [3, 2]
start_peg , inter_peg, end_peg :[]      []      [3, 2, 1]

可以使用列表列表和可选参数来保留三个列表的顺序。这样,您始终可以以相同的方式打印它们,同时根据算法需要操作项目:

def Hanoi(n,start_,inter_,end_, pegs=None):  # new optional argument
if pegs is None:
pegs = [start_, inter_, end_]  # build a list of lists if one was not passed in
if n==1:
end_.append(start_.pop()) # using pop makes this much easier
print('start_peg , inter_peg, end_peg :{}t{}t{}'.format(*pegs)) # prints in order
else:
Hanoi(n-1,start_,end_,inter_, pegs) # pass on the list of lists in each recursive call
Hanoi(1,start_,inter_,end_, pegs)   # this lets the original order be preserved
Hanoi(n-1,inter_,start_,end_, pegs)
n=3
A=list(range(n,0,-1))
B,C=[],[]
Hanoi(n, A, B, C)

我对你的代码做了一个偶然的更改,以调用list.pop而不是索引,然后调用remove来摆脱最后一项。这更有效(O(1)而不是O(N)(,也更简单!

更重要的更改是使用列表pegs列表来保留进行原始调用时三个列表的顺序。print可以使用它来以一致的顺序将它们全部写出来。

如何在没有全局变量的情况下用列表表示每个步骤?

答案很简单。只需使用您传入的变量的名称:

print('start_peg , inter_peg, end_peg :{}t{}t{}'.format(start_, inter_, end_))

这就是python处理对象的方式。对象绑定到给定作用域中的名称,但 if 可以在多个作用域中命名。您可以将对象绑定到任意数量的名称。

例如,假设您有(在函数外部(

n = 3
A = list(range(n, 0, -1))
B = []
C = []

赋值将四个不同的对象(一个int和三个list(绑定到全局命名空间中的四个不同名称(nABC(。现在当你打电话

Hanoi(n, A, B, C)

这四个对象绑定到函数命名空间中的名称nstart_inter_end_。无论使用全局名称A还是本地名称start_,您都在引用内存中的同一对象。

在不相关的注释中,start_.remove(start_[-1])对已知道其索引的对象执行不必要的按值搜索。由于您已经将值分配给上面行上的正确堆栈,因此执行删除的更简单方法是

del start_[-1]

一个更优雅的解决方案可能是将这两行都替换为

end_.append(start.pop())

您可以使用第一个元素"命名"列表:

n=3, A=["A"]+list(range(n,0,-1)), B=["B"], C=["C"]

并修改打印语句:

print('start_peg , inter_peg, end_peg :{}t{}t{}'.format( *sorted((start_, inter_, end_)) ))

排序将在"A","B","C"上生效。

编辑:如果你不喜欢上面的解决方案,你可以创建一个新类:

class Hanoi:
def __init__(self,start_):
self.n= len(start_)
self.A,self.B,self.C= start_,[],[]

def go(self):
self.Hanoi(self.n,self.A,self.B,self.C)

def Hanoi(self,n,start_,inter_,end_): # <--- your code
if n==1:
end_.append(start_[-1])
start_.remove(start_[-1])
print(self)
else:
self.Hanoi(n-1,start_,end_,inter_)
self.Hanoi(1,start_,inter_,end_)
self.Hanoi(n-1,inter_,start_,end_)
def __str__(self):
return 'start_peg, inter_peg, end_peg :{}t{}t{}'.format(self.A,self.B,self.C)
def get_pegs(self):
return self.A,self.B,self.C

#h=Hanoi(list(range(3,0,-1)))
h=Hanoi([3,2,1])
h.go()
A,B,C= h.get_pegs()
print(A,B,C)
Out:
start_peg, inter_peg, end_peg :[3, 2]   []  [1]
start_peg, inter_peg, end_peg :[3]  [2] [1]
start_peg, inter_peg, end_peg :[3]  [2, 1]  []
start_peg, inter_peg, end_peg :[]   [2, 1]  [3]
start_peg, inter_peg, end_peg :[1]  [2] [3]
start_peg, inter_peg, end_peg :[1]  []  [3, 2]
start_peg, inter_peg, end_peg :[]   []  [3, 2, 1]
[] [] [3, 2, 1]

相关内容