递归函数内的Global Count



我观看了一段关于河内塔的视频,并跟着编写了解决这个问题的脚本。代码运行得很好,但是我想在函数中添加一个计数器,这样我就可以用索引打印每一步,以便后续操作。
我尝试使用全局变量来计算递归函数调用的次数,并使用此计数作为我的索引,但仍然不能让它正常工作…我在这里做错了什么?

count = 0

def tower(n, start, end, middle):
global count
if n == 1:
count += 1
print('%i - Coloque o disco %i do pino %s no pino %s' % (count, n, start, end))
else:
count += 1
tower(n - 1, start, middle, end)
print('%i - Coloque o disco %i do pino %s no pino %s' % (count, n, start, end))
tower(n - 1, middle, end, start)

tower(5, 'A', 'C', 'B')

现在输出是这样的:

5 - Coloque o disco 1 do pino A no pino C
5 - Coloque o disco 2 do pino A no pino B
6 - Coloque o disco 1 do pino C no pino B
6 - Coloque o disco 3 do pino A no pino C
8 - Coloque o disco 1 do pino B no pino A
8 - Coloque o disco 2 do pino B no pino C
9 - Coloque o disco 1 do pino A no pino C
9 - Coloque o disco 4 do pino A no pino B
12 - Coloque o disco 1 do pino C no pino B
12 - Coloque o disco 2 do pino C no pino A
13 - Coloque o disco 1 do pino B no pino A
13 - Coloque o disco 3 do pino C no pino B
15 - Coloque o disco 1 do pino A no pino C
15 - Coloque o disco 2 do pino A no pino B
16 - Coloque o disco 1 do pino C no pino B
16 - Coloque o disco 5 do pino A no pino C
20 - Coloque o disco 1 do pino B no pino A
20 - Coloque o disco 2 do pino B no pino C
21 - Coloque o disco 1 do pino A no pino C
21 - Coloque o disco 3 do pino B no pino A
23 - Coloque o disco 1 do pino C no pino B
23 - Coloque o disco 2 do pino C no pino A
24 - Coloque o disco 1 do pino B no pino A
24 - Coloque o disco 4 do pino B no pino C
27 - Coloque o disco 1 do pino A no pino C
谁能解释一下为什么计数器没有按我想要的方式工作?

问题是当n == 1时才开始打印,因为它是递归的,但是每次调用递归时都要添加计数。

你可以通过将count add移到else语句的print前面来解决这个问题,像这样:

count = 0

def tower(n, start, end, middle):
global count
if n == 1:
count += 1
print('%i - Coloque o disco %i do pino %s no pino %s' % (count, n, start, end))
else:
tower(n - 1, start, middle, end)
count += 1
print('%i - Coloque o disco %i do pino %s no pino %s' % (count, n, start, end))
tower(n - 1, middle, end, start)

tower(5, 'A', 'C', 'B')

输出如下:

1 - Coloque o disco 1 do pino A no pino C
2 - Coloque o disco 2 do pino A no pino B
3 - Coloque o disco 1 do pino C no pino B
4 - Coloque o disco 3 do pino A no pino C
5 - Coloque o disco 1 do pino B no pino A
6 - Coloque o disco 2 do pino B no pino C
7 - Coloque o disco 1 do pino A no pino C
8 - Coloque o disco 4 do pino A no pino B
9 - Coloque o disco 1 do pino C no pino B
10 - Coloque o disco 2 do pino C no pino A
11 - Coloque o disco 1 do pino B no pino A
12 - Coloque o disco 3 do pino C no pino B
13 - Coloque o disco 1 do pino A no pino C
14 - Coloque o disco 2 do pino A no pino B
15 - Coloque o disco 1 do pino C no pino B
16 - Coloque o disco 5 do pino A no pino C
17 - Coloque o disco 1 do pino B no pino A
18 - Coloque o disco 2 do pino B no pino C
19 - Coloque o disco 1 do pino A no pino C
20 - Coloque o disco 3 do pino B no pino A
21 - Coloque o disco 1 do pino C no pino B
22 - Coloque o disco 2 do pino C no pino A
23 - Coloque o disco 1 do pino B no pino A
24 - Coloque o disco 4 do pino B no pino C
25 - Coloque o disco 1 do pino A no pino C
26 - Coloque o disco 2 do pino A no pino B
27 - Coloque o disco 1 do pino C no pino B
28 - Coloque o disco 3 do pino A no pino C
29 - Coloque o disco 1 do pino B no pino A
30 - Coloque o disco 2 do pino B no pino C
31 - Coloque o disco 1 do pino A no pino C

重复条件可能比重复计数和打印更短:

conta = 0
def tower(disco, doPino, noPino, tempPino):
global conta    
if disco>1: tower(disco - 1, doPino, tempPino, noPino)
conta += 1
print(f'{conta} - Coloque o disco {disco} do pino {doPino} no {noPino}')
if disco>1: tower(disco - 1, tempPino, noPino, doPino)

通过在两个递归调用之间放置print和count,在将磁盘nstart移动到end之前需要做的所有事情将在移动本身被打印之前被打印(并计数)。之后需要发生的所有其他移动都被第二次递归调用打印出来。当n为1时,上面没有磁盘,因此该函数只是打印并计算单次移动。

在这种情况下,第一个调用是将磁盘5从'A'移动到'C'。但在此之前,碟片5上面的每个碟片都需要移动到"B"。所以我们让第一个递归调用完成这个。然后我们打印移动(第5盘从'A'到'C')。这将在'B'位置留下一堆磁盘(1,2,3,4),因此第二次递归调用将处理将磁盘1,2,3,4从'B'移动到'C',并将在移动磁盘5后打印。

简而言之,要将圆盘1、2、3、4、5从"A"移动到"C",我们有:

tower(5,'A','C','B'):
# perform/print/count all moves to get discs 1,2,3,4 from 'A' to 'B'
# print/count move disc 5 from 'A' to 'C'
# perform/print/count all moves to get discs 1,2,3,4 from 'B' to 'C'

最新更新