Recursive Data into an inverse hill
list = input("Enter data:")
k = [*map(int,list.split())]
l=[k]
while len(l[-1])>1:
k=[k[i]-k[i-1]for i in range(1,len(k))]
l+=[k]
print(*k)
INPUT: 10 20 30 40 50
OUTPUT:
10 10 10 10
0 0 0
0 0
0
I want the output to be in an inverse hill or triangle just like:
10 10 10 10
0 0 0
0 0
0
You can modify or overhaul my code.
Solution 1:
You can use zip to obtain the differences between items of a list and their successor. If you're only printing as you go, you don't need to store the differences in a separate list
To get a good alignment, you would need to control the printing width of each number and the width of the spacing between them. In that case it would be easier to use a fixed width corresponding to the largest number (and use it as spacing as well):
k = [8,13,21,34,55,89]
width = len(str(max(k))) # fixed width numbers/spacing
for i in range(len(k)-1): # i will provide indentation
k = [b-a for a,b in zip(k,k[1:])] # update with differences
fw = (f"{n:<{2*width}}" for n in k) # fixed width numbers
print(" "*width*i, *fw, sep="") # print with indentation
5 8 13 21 34
3 5 8 13
2 3 5
1 2
1
To include the initial content of k in the output, you simply need to loop one more time and move the update of k to after printing it:
k = [8,13,21,34,55,89]
width = len(str(max(k))) # fixed width numbers/spacing
for i in range(len(k)): # i will provide indentation
fw = (f"{n:<{2*width}}" for n in k) # fixed width numbers
print(" "*width*i, *fw, sep="") # print with indentation
k = [b-a for a,b in zip(k,k[1:])] # update with differences
8 13 21 34 55 89
5 8 13 21 34
3 5 8 13
2 3 5
1 2
1
If it is possible to get negative differences, you should make the width be at least 2 (or +1) to have room for the minus signs
If you're not comfortable with format strings, str(n).ljust(2*width)
would do the same thing as f"{n:<{2*width}}"
[EDIT] Using fixed widths is easier but it does waste a bit of horizontal space. If you want to reduce the horizontal space consumption while avoiding ambiguous overlapping of numbers, you will need to process the numbers in two steps: 1) build the list of values in a 2D matrix with values on odd lines placed in odd columns and even lines on even columns. 2) Concatenate the values on each line ensuring every column has the same (largest) width.
k = [8,13,21,34,55,89]
lines = [['']*len(k)*2 for _ in k[1:]] # prepare with enough columns
for i in range(len(k)-1): # i will be indent
k = [b-a for a,b in zip(k,k[1:])] # update with differences
lines[i][i:i+len(k)*2:2] = map(str,k) # numbers at odd/even columns
widths = [max(map(len,c)) for c in zip(*lines)] # largest column widths
for line in lines: # print with adjusted widths
print( "".join(s.ljust(w) for s,w in zip(line,widths)) )
5 8 13 21 34
3 5 8 13
2 3 5
1 2
1
The lines
matrix has the values organized in the appropriate column to produce an inverted pyramid. By ensuring a consistent width on each column, the amount of horizontal space is optimized and the layout meets the requirement:
['5', '', '8', '', '13', '', '21', '', '34', '', '', '']
['', '3', '', '5', '', '8', '', '13', '', '', '', '']
['', '', '2', '', '3', '', '5', '', '', '', '', '']
['', '', '', '1', '', '2', '', '', '', '', '', '']
['', '', '', '', '1', '', '', '', '', '', '', '']
If you want the initial input to be part of the reversed hill:
k = [8,13,21,34,55,89]
lines = [['']*len(k)*2 for _ in k] # prepare with enough columns
for i in range(len(k)): # i will be indent
lines[i][i:i+len(k)*2:2] = map(str,k) # numbers at odd/even columns
k = [b-a for a,b in zip(k,k[1:])] # update with differences
widths = [max(map(len,c)) for c in zip(*lines)] # largest column widths
for line in lines: # print with adjusted widths
print( "".join(s.ljust(w) for s,w in zip(line,widths)) )
8 13 21 34 55 89
5 8 13 21 34
3 5 8 13
2 3 5
1 2
1
Solution 2:
I slightly modified your print
statement:
k = [*map(int,list.split())]
l=[k]
spaces = 0
while len(l[-1])>1:
k=[k[i]-k[i-1]for i in range(1,len(k))]
l+=[k]
print(' '.join(map(str, k)).center(len(k)*2-1+spaces))
spaces += 2
Output:
1 1 1 1
0 0 0
0 0
0