简体   繁体   中英

How do I print a list in a triangular shape in python?

I have a code that generates a list of values to form a Romberg Triangle. The list is always a triangular length (3, 6, 10, 15). How do I print a list like this in triangular form?

What I currently have:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Print statement that I want:

1 
2 5 
3 6 8
4 7 9 10

Try this:

def getLength(n):
    i = 1
    s = 1
    while ( s < n ):
        i += 1
        s = s + i
    return i

def printTriangle(a):
    l = len(a)
    lt = getLength(l)
    for i in range(lt):
        d = lt - 2
        s = 0
        for j in range(i+1):
            print(a[i+j+s], end=' ')
            s += d
            d -= 1
        print('')

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

printTriangle(a)

The getLength function just calculates the height of the triangle and the printTriangle function handles the actual printing logic.

A different approach:

def print_tri(l):
    n_rows = 1
    n_elements = 1
    while n_elements < len(l):
        n_rows += 1
        n_elements += n_rows

    rows = [[] for _ in range(n_rows)]
    offset = 0
    while l:
        for d in range(offset, n_rows):
            rows[d].append(l.pop(0))
        offset += 1

    for row in rows:
        print(' '.join(map(str, row)))

print_tri([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

One can go full-math, solving length=(n*(n+1))/2 for n (number of rows and columns, it has one positive solution), and then use the sum of arithmetic progression for calculating indices for the columns (what the older variant below does using sum ):

def tri(lst):
  rows=int(((1+8*len(lst))**0.5-1)/2)
  for row in range(0,rows):
    print([lst[int(row+(2*rows-column-1)*column/2)] for column in range(0,row+1)])
  print() # this is just for separating subsequent calls

tri([1])
tri([1,2,3])
tri([1,2,3,4,5,6])
tri([1,2,3,4,5,6,7,8,9,10])
tri([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15])

Output:

 [1] [1] [2, 3] [1] [2, 4] [3, 5, 6] [1] [2, 5] [3, 6, 8] [4, 7, 9, 10] [1] [2, 6] [3, 7, 10] [4, 8, 11, 13] [5, 9, 12, 14, 15]


An older variant collecting column-lengths first, and then indexing into the list directly:

 a=list(range(1,11)) lena=len(a) deltas=[] total=0 i=0 while total<lena: deltas.append(i) i+=1 total+=i lend=len(deltas) for row in range(lend): print([a[row+sum(deltas[lend-column:])] for column in range(0,row+1)])

The following works fairly efficiently:

def print_triangle(x):
    it = iter(x)
    num = 0
    while True:
        val = next(it, None)
        if val:
            print(val, *(next(it) for _ in range(num)))
            num += 1
        else:
            break
>>> print_triangle([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
1
2 3
4 5 6
7 8 9 10
>>> print_triangle([1, 2, 3, 4, 5, 6])
1
2 3
4 5 6

Will fail if the input doesn't have the correct length:

>>> print_triangle([1, 2, 3, 4, 5])
1
2 3
Traceback (most recent call last):
  File "<stdin>", line 7, in <genexpr>
StopIteration

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in print_triangle
RuntimeError: generator raised StopIteration

I have used a lot of mathematics! n is the side of triangle (I have used delta equation to calculate that). l is the list of numbers you can give to the function. I hope the rest would be understandable.! Feel free to ask questions in comment.

def print_triang(l):
    lg = len(l)
    number_of_rows = int(((1+8*lg)**.5 - 1) / 2)
    for row_index in range(number_of_rows):
        print(' '.join(
            str(l[x]) for x in [row_index + col_index*number_of_rows - int(col_index*(col_index+1)/2) for col_index in range(row_index+1)]
    ))

You can also use next with iter :

def is_side(d, s):
  return not d if not s else is_side(d[s:], s-1)

def to_triangle(d):
   new_d, r = iter(d), [i for i in range(len(d)) if is_side(d, i)][0]
   s = [[next(new_d) for _ in range(i)] for i in reversed(range(1, r+1))]
   return '\n'.join(' '.join(str(b[x]) if (x:=len(b) - len(s[0])+i) >= 0 else ' ' for b in s) for i in range(len(s[0])))

d = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(to_triangle(d))

Output:

1      
2 5    
3 6 8  
4 7 9 10

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM