问题
I need to write a function to generate Pascal's Triangle as a tuple using recursion.
e.g pascal(5)
((1,), (1, 1), (1, 2, 1), (1, 3, 3, 1), (1, 4, 6, 4, 1))
I can generate it as a list with the following function:
def triangle(n):
if n == 0:
return []
elif n == 1:
return [[1]]
else:
new_row = [1]
result = triangle(n-1)
last_row = result[-1]
for i in range(len(last_row)-1):
new_row.append(last_row[i] + last_row[i+1])
new_row += [1]
result.append(new_row)
return result
And I've tried changing this to a tuple:
def pascal(n):
if n==0:
return ()
elif n==1:
return ((1,),)
else:
new_row = (1,)
result = pascal(n-1)
last_row = result[-1]
print(last_row)
for i in range(len(last_row)-1):
new_row = new_row+last_row[i]+last_row[i+1]
new_row = new_row +(1,)
result=result+(new_row,)
return result
but it doesn't work and I get the error len(last_row)-1 type int has no len
.
I'm not sure how to fix this code and would appreciate any help.
回答1:
I think the problem is the result = result + new_row
line.
If you want to see why, mouseover below...
result
is a tuple of tuples,new_row
is a tuple of numbers. If you add a tuple of numbers to a tuple of tuples, you end with a tuple of tuples and numbers! Such as((1,), 1)
which is not what you want. fix it by doingresult = result + (new_row,)
回答2:
In your first code, simply add this line before the return
in order to convert the list of lists
to tuple of tuples
:
tuple_results = tuple(tuple(x) for x in results)
return tuple_results
回答3:
NOTE
Don't turn this in for homework. Your teacher will (correctly) gather that you cribbed it from the net. Primarily for learning purposes in terms of how compact this can be, i.e. how a professional Python programmer might write this.
So here it is, the short 8 line version:
def pascal(n):
if n <= 0:
return ()
elif n == 1:
return ((1,),)
else:
res = pascal(n - 1) # recursive call
return (*res, (1, *[n + i for n, i in zip(res[-1], res[-1][1:])], 1))
print(pascal(5))
In this case, the part that was missing from your code is the spread operator. What it does is unpack that tuple of tuples from the recursive call to which you tack on the next row.
This is pretty dense, so lets unpack it a little:
return (*res, # open paren starts new tuple, *res unpacks the recursive call
(1, # starts the tuple for the current row
*[ # spread the result of the list comprehension
n + i for n, i in # we're going to add the items in two lists
zip( # here's where we combine the two lists to add
res[-1], # last row of recursive call
res[-1][1:] # same but shifted 1 index
),
], # end list comprehension
1) # 1 to end the current row
) # end the total result, i.e. tuple of rows
This works because of how zip
deals with lists of different lengths. For example, if the last row was (1,3,3,1)
then we'd get zip((1,3,3,1),(3,3,1))
which would be ((1,3), (3,3), (3,1))
. Then we add the digits in the pairs in the comprehension and get (4,6,4)
. Tack on the ones and there's the next row.
来源:https://stackoverflow.com/questions/42906045/attempting-to-generate-pascals-triangle-as-a-tuple-using-recursion