我在这个帕斯卡三角形生成器中做错了什么?

What am I doing wrong in this Pascal's triangle generator?

提问人:Zey Roax 提问时间:7/11/2023 最后编辑:Zey Roax 更新时间:7/12/2023 访问量:84

问:

我正在尝试使用 Python 打印帕斯卡三角形。我正在使用嵌套列表和循环。它的工作原理是这样的。对于 n = 2,它应该打印:

  1
 1 1
1 2 1

这是我的代码:

n = int(input("Enter the limit: "))
triangle = []
currentRow = 0
for currentRow in range(n+1):
    spaces = n - currentRow
    printables = currentRow - 1
    temp = []
    while spaces > 0:
        temp.append(" ")
        spaces -= 1
    while printables > 0:
        if currentRow == 0:
            temp.append("1")
            triangle.append(temp)
            temp.clear()
        else:
            try:
                if (triangle[currentRow - 1][(spaces + 1) - 1]) == " " or (triangle[currentRow - 1][(spaces + 1) + 1]) == " ":
                    temp.append("1 ")
                else:
                    temp.append(f"{int(triangle[currentRow - 1][(spaces - 1) + 1]) + int(triangle[currentRow - 1][(spaces + 1) + 1])} ")
                triangle.append(temp)
                temp.clear()
            except IndexError:
                pass
print(triangle)

我不知道为什么,但即使我不断地将我的值附加到它,它也不会为三角形列表打印任何内容。有人请帮忙。

Python 数组 列表 嵌套 的循环

评论


答:

1赞 the_strange 7/11/2023 #1

您只设置了一次,但循环的条件会检查 。如果不更改 的值,则循环将永远不会终止。printableswhileprintables > 0printables

评论

0赞 Zey Roax 7/11/2023
非常感谢。我简直不敢相信我这么笨。但是有一个新问题,我刚刚编辑到帖子中。你能帮我吗?
2赞 chepner 7/11/2023
不要在问题得到回答后对其进行编辑,也不要针对您遇到的每个绊脚石单独提出问题。花 30 秒以上的时间尝试自己解决下一个问题。
0赞 Codist 7/11/2023 #2

我建议采用三步法解决这个问题。

首先,创建一个函数,以数字形式生成帕斯卡三角形的行。

其次,构建一个字符串列表,表示三角形中的每一行。

最后,打印以最后一个(最长)字符串的宽度为中心的行。

P 是三角形中所需的行数

def pascal(n: int) -> list[list[int]]:
    r = [[1]]
    for i in range(2, n+1):
        p = r[-1]
        r.append([1] + [sum(p[j-1:j+1]) for j in range(1, i-1)] + [1])
    return r

P = 10 # number of rows in the triangle

out = [' '.join(map(str, e)) for e in pascal(P)]

w = len(out[-1]) # width of longest item

print(*(e.center(w) for e in out), sep='\n')

输出:

             1             
            1 1            
           1 2 1           
          1 3 3 1          
         1 4 6 4 1         
       1 5 10 10 5 1       
      1 6 15 20 15 6 1     
    1 7 21 35 35 21 7 1    
   1 8 28 56 70 56 28 8 1  
1 9 36 84 126 126 84 36 9 1

评论

0赞 Zey Roax 7/11/2023
我没有得到您添加宽度的部分。尽管这一切都很复杂,但您能解释一下宽度部分吗?
0赞 Codist 7/11/2023
@ZeyRoax Python 字符串对象(str 类型)有一个名为 center() 的内置函数 你可以在这里阅读它: docs.python.org/3/library/stdtypes.html#text-sequence-type-str
0赞 Zey Roax 7/11/2023
我知道这一点,但是您使用地图进行计算的方式是无法理解的。您是否只是合并了所有列表,然后在最后一行执行了 -1?是这样吗?
0赞 Codist 7/11/2023
@ZeyRoax 索引值 -1 是指非零长度列表中的最后一项。三角形的构造使得最后一行是最长的。因此,很容易计算出所需的最大宽度,然后围绕该宽度将所有较短的行居中
0赞 user21508463 7/11/2023 #3

不是答案,只是一个稍微紧凑一点的解决方案。

P= []
for k in range(10):
    for i in range(len(P)-1, 0, -1):
        P[i]+= P[i-1]
    P.append(1)
    print(P)

输出:

[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
[1, 6, 15, 20, 15, 6, 1]
[1, 7, 21, 35, 35, 21, 7, 1]
[1, 8, 28, 56, 70, 56, 28, 8, 1]
[1, 9, 36, 84, 126, 126, 84, 36, 9, 1]

或者使用隐式循环,

P=[]
for k in range(10):
    P= [1] + [P[i] + (P[i+1] if i+1 < len(P) else 0) for i in range(len(P))]
    print(P)

评论

0赞 Zey Roax 7/11/2023
你能向我解释一下 len(p)-1, 0, -1 部分吗?对于其他一切。知道了。
0赞 7/11/2023
@ZeyRoax:它只是一个向后循环,以避免修改仍然需要的值。
0赞 Zey Roax 7/11/2023
那么为什么第一种方法没有错误,长度将是 0 并且 0-1 = -1,我们无法通过从 -1 向后退到达 0。
0赞 7/11/2023
@ZeyRoax:循环不执行,这是预期的行为。
0赞 Zey Roax 7/11/2023
哦,谢谢。这种方法太简单了。非常感谢。我已经为我的长期方法工作了 3 天。你他妈的疯了!最后一件事,我能知道你从哪里学到所有这些高级的东西吗?我也想学习它。
0赞 Alain T. 7/12/2023 #4

您的代码过于复杂,因为您正在尝试将计算与格式化相结合。此外,虽然循环比 for 循环更容易出错,但您应该在此处使用循环,因为所有迭代都是可预测的。

因此,您应该改变将计算(构建数字列表)和格式(缩进、间距和打印)分开的方法。

如果您希望输出很好地平衡,您可以打印具有固定宽度(基于最大值)的数字,并根据最大总宽度将每行居中。

为了知道值的打印宽度,您可以事先生成所有帕斯卡三角形线,并以字符串的形式测量最大数字的大小。

# pascal triangle lines
N = 10
P = [[1]]  
P.extend( [1,*map(sum,zip(P[-1],P[-1][1:])),1] for _ in range(1,N) )

# determine fixed value printing width 
width  = len(str(max(P[-1]))) + 2 # extra for spacing (* 2 for no overlap)

# print each line centred, with centred numbers
for line in P:
    print("".join(str(n).center(width) for n in line).center(width*N))

N = 10 时的输出:

                             1                              
                          1     1                           
                       1     2     1                        
                    1     3     3     1                     
                 1     4     6     4     1                  
              1     5     10    10    5     1               
           1     6     15    20    15    6     1            
        1     7     21    35    35    21    7     1         
     1     8     28    56    70    56    28    8     1      
  1     9     36    84   126   126    84    36    9     1  

N = 9 时的输出:

                 1                  
               1   1                
             1   2   1              
           1   3   3   1            
         1   4   6   4   1          
       1   5   10  10  5   1        
     1   6   15  20  15  6   1      
   1   7   21  35  35  21  7   1    
 1   8   28  56  70  56  28  8   1 

您也可以随时计算帕斯卡线,但您需要估计最大值的大小才能获得正确的格式。对于帕斯卡三角形,每条线上的数字之和为 2^N,因此一条线的最大值最多为该值的一半。

# pascal triangle size
N = 10

# estimate fixed value printing width
width  = len(str(2**(N-1))) + 2 # extra for spacing

# print each line centred, with centred numbers
P = [1]
for i in range(N):
    print("".join(str(n).center(width) for n in P).center(width*N))
    P = [1,*map(sum,zip(P,P[1:])),1] # compute next line


                             1                              
                          1     1                           
                       1     2     1                        
                    1     3     3     1                     
                 1     4     6     4     1                  
              1     5     10    10    5     1               
           1     6     15    20    15    6     1            
        1     7     21    35    35    21    7     1         
     1     8     28    56    70    56    28    8     1      
  1     9     36    84   126   126    84    36    9     1 

为了使它更简洁,您应该将帕斯卡线计算完全隔离在一个函数中,然后在格式化/打印代码中使用该函数:

计算:

def pascalLine(N):
    r = [1]
    for p in range(N): 
        r.append(r[-1]*(N-p)//(p+1))
    return r

排版和打印:

N     = 10
width = len(str(max(pascalLine(N-1))))*2
for i in range(N):
    line = "".join(f"{n:^{width}}" for n in pascalLine(i)).center(width*N)
    print(line)

                             1                              
                          1     1                           
                       1     2     1                        
                    1     3     3     1                     
                 1     4     6     4     1                  
              1     5     10    10    5     1               
           1     6     15    20    15    6     1            
        1     7     21    35    35    21    7     1         
     1     8     28    56    70    56    28    8     1      
  1     9     36    84   126   126    84    36    9     1