作为Python的学习经验,我正在尝试编写自己版本的Pascal三角形。我花了几个小时(因为我刚刚开始),但我出来了这段代码:
pascals_triangle = []
def blank_list_gen(x):
while len(pascals_triangle) < x:
pascals_triangle.append([0])
def pascals_tri_gen(rows):
blank_list_gen(rows)
for element in range(rows):
count = 1
while count < rows - element:
pascals_triangle[count + element].append(0)
count += 1
for row in pascals_triangle:
row.insert(0, 1)
row.append(1)
pascals_triangle.insert(0, [1, 1])
pascals_triangle.insert(0, [1])
pascals_tri_gen(6)
for row in pascals_triangle:
print(row)
返回
[1]
[1, 1]
[1, 0, 1]
[1, 0, 0, 1]
[1, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 0, 1]
但是,我不知道从哪里开始。我一直在墙上撞了好几个小时。我想强调一点,我不希望你为我做这件事;只是把我推向正确的方向。作为列表,我的代码返回
[[1], [1, 1], [1, 0, 1], [1, 0, 0, 1], [1, 0, 0, 0, 1], [1, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 1]]
感谢。
编辑:我提出了一些很好的建议,我完全重写了我的代码,但我现在遇到了另一个问题。这是我的代码。import math
pascals_tri_formula = []
def combination(n, r):
return int((math.factorial(n)) / ((math.factorial(r)) * math.factorial(n - r)))
def for_test(x, y):
for y in range(x):
return combination(x, y)
def pascals_triangle(rows):
count = 0
while count <= rows:
for element in range(count + 1):
[pascals_tri_formula.append(combination(count, element))]
count += 1
pascals_triangle(3)
print(pascals_tri_formula)
但是,我发现输出有点不受欢迎:
[1, 1, 1, 1, 2, 1, 1, 3, 3, 1]
我该如何解决这个问题?
答案 0 :(得分:14)
确定代码审核:
import math
# pascals_tri_formula = [] # don't collect in a global variable.
def combination(n, r): # correct calculation of combinations, n choose k
return int((math.factorial(n)) / ((math.factorial(r)) * math.factorial(n - r)))
def for_test(x, y): # don't see where this is being used...
for y in range(x):
return combination(x, y)
def pascals_triangle(rows):
result = [] # need something to collect our results in
# count = 0 # avoidable! better to use a for loop,
# while count <= rows: # can avoid initializing and incrementing
for count in range(rows): # start at 0, up to but not including rows number.
# this is really where you went wrong:
row = [] # need a row element to collect the row in
for element in range(count + 1):
# putting this in a list doesn't do anything.
# [pascals_tri_formula.append(combination(count, element))]
row.append(combination(count, element))
result.append(row)
# count += 1 # avoidable
return result
# now we can print a result:
for row in pascals_triangle(3):
print(row)
打印:
[1]
[1, 1]
[1, 2, 1]
这是"n choose k"的公式(即有多少种不同的方式(无视顺序),从n项的有序列表中,我们可以选择k项):
from math import factorial
def combination(n, k):
"""n choose k, returns int"""
return int((factorial(n)) / ((factorial(k)) * factorial(n - k)))
一位评论者询问这是否与itertools.combinations有关 - 事实确实如此。 &#34; n选择k&#34;可以通过从组合中获取元素列表的长度来计算:
from itertools import combinations
def pascals_triangle_cell(n, k):
"""n choose k, returns int"""
result = len(list(combinations(range(n), k)))
# our result is equal to that returned by the other combination calculation:
assert result == combination(n, k)
return result
让我们看看这个证明:
from pprint import pprint
ptc = pascals_triangle_cell
>>> pprint([[ptc(0, 0),],
[ptc(1, 0), ptc(1, 1)],
[ptc(2, 0), ptc(2, 1), ptc(2, 2)],
[ptc(3, 0), ptc(3, 1), ptc(3, 2), ptc(3, 3)],
[ptc(4, 0), ptc(4, 1), ptc(4, 2), ptc(4, 3), ptc(4, 4)]],
width = 20)
[[1],
[1, 1],
[1, 2, 1],
[1, 3, 3, 1],
[1, 4, 6, 4, 1]]
我们可以避免重复使用嵌套列表理解:
def pascals_triangle(rows):
return [[ptc(row, k) for k in range(row + 1)] for row in range(rows)]
>>> pprint(pascals_triangle(15))
[[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],
[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1],
[1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1],
[1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1],
[1, 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1],
[1, 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1]]
我们可以使用三角形所示的关系递归地定义(效率较低,但可能更具数学优雅的定义):
def choose(n, k): # note no dependencies on any of the prior code
if k in (0, n):
return 1
return choose(n-1, k-1) + choose(n-1, k)
为了好玩,您可以看到每一行的执行时间越来越长,因为每行必须每次重新计算前一行中的每个元素两次:
for row in range(40):
for k in range(row + 1):
# flush is a Python 3 only argument, you can leave it out,
# but it lets us see each element print as it finishes calculating
print(choose(row, k), end=' ', flush=True)
print()
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
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 1
1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1
1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1
1 15 105 455 1365 3003 5005 6435 6435 5005 3003 1365 455 105 15 1
1 16 120 560 1820 4368 8008 11440 12870 11440 8008 4368 1820 560 120 16 1
1 17 136 680 2380 6188 12376 19448 24310 24310 19448 12376 6188 2380 680 136 17 1
1 18 153 816 3060 8568 18564 31824 43758 48620 43758 31824 18564 8568 3060 816 ...
当你厌倦了观看它时退出Ctrl-C,它会变得非常慢......
答案 1 :(得分:10)
我知道你想要自己实现,但我解释的最好方法是完成一个实现。这是我如何做到的,这个实现依赖于我对Python函数如何工作的相当完整的知识,所以你可能不想自己想使用这个代码,但它可能会让你指向正确的方向。
def pascals_triangle(n_rows):
results = [] # a container to collect the rows
for _ in range(n_rows):
row = [1] # a starter 1 in the row
if results: # then we're in the second row or beyond
last_row = results[-1] # reference the previous row
# this is the complicated part, it relies on the fact that zip
# stops at the shortest iterable, so for the second row, we have
# nothing in this list comprension, but the third row sums 1 and 1
# and the fourth row sums in pairs. It's a sliding window.
row.extend([sum(pair) for pair in zip(last_row, last_row[1:])])
# finally append the final 1 to the outside
row.append(1)
results.append(row) # add the row to the results.
return results
用法:
>>> for i in pascals_triangle(6):
... print(i)
...
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
答案 2 :(得分:5)
不使用zip,但使用生成器:
def gen(n,r=[]):
for x in range(n):
l = len(r)
r = [1 if i == 0 or i == l else r[i-1]+r[i] for i in range(l+1)]
yield r
示例:
print(list(gen(15)))
输出
[[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], [1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1], [1, 11, 55, 165, 330, 462, 462, 330, 165, 55, 11, 1], [1, 12, 66, 220, 495, 792, 924, 792, 495, 220, 66, 12, 1], [1, 13, 78, 286, 715, 1287, 1716, 1716, 1287, 715, 286, 78, 13, 1], [1, 14, 91, 364, 1001, 2002, 3003, 3432, 3003, 2002, 1001, 364, 91, 14, 1]]
以三角形显示
以漂亮的三角形绘制(仅适用于n <7,超出此范围时会被分散。参考draw_beautiful为n&gt; 7)
对于n&lt; 7
def draw(n):
for p in gen(n):
print(' '.join(map(str,p)).center(n*2)+'\n')
<强>例如强>
draw(10
)
输出
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
适用于任何尺寸
因为我们需要知道最大宽度,所以我们无法使用发生器
def draw_beautiful(n):
ps = list(gen(n))
max = len(' '.join(map(str,ps[-1])))
for p in ps:
print(' '.join(map(str,p)).center(max)+'\n')
例子(2): 适用于任何数字:
draw_beautiful(100)
答案 3 :(得分:2)
这是我的尝试:
def generate_pascal_triangle(rows):
if rows == 1: return [[1]]
triangle = [[1], [1, 1]] # pre-populate with the first two rows
row = [1, 1] # Starts with the second row and calculate the next
for i in range(2, rows):
row = [1] + [sum(column) for column in zip(row[1:], row)] + [1]
triangle.append(row)
return triangle
for row in generate_pascal_triangle(6):
print row
zip()
来电基本上将两个相邻的数字组合在一起zip()
调用仅生成下一行的中间答案 4 :(得分:1)
def pascal(n):
if n==0:
return [1]
else:
N = pascal(n-1)
return [1] + [N[i] + N[i+1] for i in range(n-1)] + [1]
def pascal_triangle(n):
for i in range(n):
print pascal(i)
答案 5 :(得分:1)
这是一个优雅而有效的递归解决方案。我正在使用非常方便的toolz库。
from toolz import memoize, sliding_window
@memoize
def pascals_triangle(n):
"""Returns the n'th row of Pascal's triangle."""
if n == 0:
return [1]
prev_row = pascals_triangle(n-1)
return [1, *map(sum, sliding_window(2, prev_row)), 1]
pascals_triangle(300)
在macbook pro(2.9 GHz Intel Core i5)上大约需要15 ms。请注意,在不增加默认递归深度限制的情况下,您可以更高。
答案 6 :(得分:0)
# combining the insights from Aaron Hall and Hai Vu,
# we get:
def pastri(n):
rows = [[1]]
for _ in range(1, n+1):
rows.append([1] +
[sum(pair) for pair in zip(rows[-1], rows[-1][1:])] +
[1])
return rows
# thanks! learnt that "shape shifting" data,
# can yield/generate elegant solutions.
答案 7 :(得分:0)
# call the function ! Indent properly , everything should be inside the function
def triangle():
matrix=[[0 for i in range(0,20)]for e in range(0,10)] # This method assigns 0's to all Rows and Columns , the range is mentioned
div=20/2 # it give us the most middle columns
matrix[0][div]=1 # assigning 1 to the middle of first row
for i in range(1,len(matrix)-1): # it goes column by column
for j in range(1,20-1): # this loop goes row by row
matrix[i][j]=matrix[i-1][j-1]+matrix[i-1][j+1] # this is the formula , first element of the matrix gets , addition of i index (which is 0 at first ) with third value on the the related row
# replacing 0s with spaces :)
for i in range(0,len(matrix)):
for j in range(0,20):
if matrix[i][j]==0: # Replacing 0's with spaces
matrix[i][j]=" "
for i in range(0,len(matrix)-1): # using spaces , the triangle will printed beautifully
for j in range(0,20):
print 1*" ",matrix[i][j],1*" ", # giving some spaces in two sides of the printing numbers
triangle() # calling the function
会打印出类似这样的内容
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
答案 8 :(得分:0)
我在流行的fibonacci sequence解决方案中作弊。对我来说,Pascal三角形的实现与斐波那契的概念相同。在斐波那契,我们一次使用一个数字,并将其添加到前一个数字。在pascal的三角形中,一次使用一行并将其添加到前一行。
以下是完整的代码示例:
>>> def pascal(n):
... r1, r2 = [1], [1, 1]
... degree = 1
... while degree <= n:
... print(r1)
... r1, r2 = r2, [1] + [sum(pair) for pair in zip(r2, r2[1:]) ] + [1]
... degree += 1
<强>测试强>
>>> pascal(3)
[1]
[1, 1]
[1, 2, 1]
>>> pascal(4)
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
>>> pascal(6)
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]
注意:要将结果作为生成器,请将print(r1)
更改为yield r1
。
答案 9 :(得分:0)
初学Python学生。这是我的尝试,一种非常直接的方法,使用两个For循环:
pascal = [[1]]
num = int(input("Number of iterations: "))
print(pascal[0]) # the very first row
for i in range(1,num+1):
pascal.append([1]) # start off with 1
for j in range(len(pascal[i-1])-1):
# the number of times we need to run this loop is (# of elements in the row above)-1
pascal[i].append(pascal[i-1][j]+pascal[i-1][j+1])
# add two adjacent numbers of the row above together
pascal[i].append(1) # and cap it with 1
print(pascal[i])
答案 10 :(得分:0)
这是实现Pascal三角形的简单方法:
def pascal_triangle(n):
myList = []
trow = [1]
y = [0]
for x in range(max(n,0)):
myList.append(trow)
trow=[l+r for l,r in zip(trow+y, y+trow)]
for item in myList:
print(item)
pascal_triangle(5)
Python zip()函数返回zip对象,它是元组的迭代器,其中每个传递的迭代器中的第一项配对在一起,然后每个传递的迭代器中的第二项配对在一起。 Python zip是在其中保存真实数据的容器。
Python zip()函数接受可迭代项(可以为零或多个),使其成为一个迭代器,该迭代器根据传递的可迭代项聚合项目,并返回元组的迭代器。
答案 11 :(得分:0)
当我和我的儿子一起制作 Python 介绍片时,我就这样做了。当我们瞄准时,它开始是一个相当简单的作品 -
1
1 2
1 2 3
1 2 3 4
然而,一旦我们达到实际算法,复杂性就超出了我们的预期。无论如何,我们确实构建了这个 -
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
使用了一些递归 -
def genRow(row:list) :
# print(f"generatig new row below {row}")
# printRow(row)
l = len(row) #2
newRow : list = []
i = 0
# go through the incoming list
while i <= l:
# print(f"working with i = {i}")
# append an element in the new list
newRow.append(1)
# set first element of the new row to 1
if i ==0:
newRow[i] = 1
# print(f"1:: newRow = {newRow}")
# if the element is in the middle somewhere, add the surroundng two elements in
# previous row to get the new element
# e.g. row 3[2] = row2[1] + row2[2]
elif i <= l-1:
# print(f"2:: newRow = {newRow}")
newRow[i] = row[i-1] + row[i]
else:
# print(f"3 :: newRow = {newRow}")
newRow[i] = 1
i+=1
# print(newRow)
return newRow
def printRow(mx : int, row:list):
n = len(row)
spaces = ' ' *((mx - n)*2)
print(spaces,end=' ')
for i in row:
print(str(i) + ' ',end = ' ')
print(' ')
r = [1,1]
mx = 7
printRow(mx,[1])
printRow(mx,r)
for a in range(1,mx-1):
# print(f"working for Row = {a}")
if len(r) <= 2:
a1 = genRow(r)
r=a1
else:
a2 = genRow(a1)
a1 = a2
printRow(mx,a1)
希望它有所帮助。