What’s more, we have discovered another sequence, but one that requires a general term to describe it.
1 + 2 == 3
3 + 3 == 6
6 + 4 == 10
__ + _ == __
See the pattern, and where this is going? What if we can fill in the blanks with a program, well at least the last blank…
>>> def get_seq(rows):
r = 1
if rows <= r: return [r]
s = 1
a = 2
while r < rows:
s += a
a += 1
r += 1
return list(range(1, s + 1))
>>> get_seq(4)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> get_seq(5)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
>>>
Now let’s put this to the test…
>>> row = 1
>>> sequence = [str(x) for x in get_seq(5)]
>>> while sequence:
print ("{:>14}".format(' '.join(sequence[0:row])))
del sequence[0:row]
row += 1
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
>>>
We do not need a list, when we come down to it since a range is iterable and sliceable…
>>> def get_seq(rows):
r = 1
if rows <= r: return [r]
s = 1
a = 2
while r < rows:
s += a
a += 1
r += 1
return range(1, s + 1)
>>> row = 1
>>> sequence = [str(x) for x in get_seq(5)]
>>> while sequence:
print ("{:>14}".format(' '.join(sequence[0:row])))
del sequence[0:row]
row += 1
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
>>>
To make this truly dynamic we need to know how much space is needed to print the last line for any number of rows. The following shows that we can insert a value dynamically in the syntax that denotes the space allocation in a format descriptor.
>>> row = 1
>>> sequence = [str(x) for x in get_seq(5)]
>>> while sequence:
print ("{:>{z}}".format(' '.join(sequence[0:row]), z=14))
del sequence[0:row]
row += 1
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
>>>
Pay particular note to z
in the above. It is at that point where we can perform a computation of the length of the last row. BRB
Into the logic for a dynamic solution we might have to bring in a utility…
>>> def count_rows(z):
c = 0
d = 1
while z:
z -= d
d += 1
c += 1
return c
>>> count_rows(55)
10
>>>
This is a function that can unwind the main function logic to arrive at the number of rows. z
is the last value in a given sequence. This will give us a slice length to work with in the last line size problem. Something to keep working on…
With the number, 55
we got 10
, and with that we have enough information to complete the size computation.
>>> sequence = [str(x) for x in get_seq(10)]
>>> len(' '.join(sequence[-10:]))
29
>>>
We’re exploiting some pretty cool stuff, up to this point. Are we having fun yet?
P. S. Let us know when you port this over to Swift. The credit still belongs here.
>>> row = 1
>>> s = [str(x) for x in get_seq(10)]
>>> while s:
print ("{:>{z}}".format(' '.join(s[0:row]), z=len(' '.join(s[-10:]))))
del s[0:row]
row += 1
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54 55
>>>
Think we’re getting somewhere…
>>> row = 1
>>> rows = 15
>>> seq = [str(x) for x in get_seq(rows)]
>>> z = len(' '.join(seq[-rows:]))
>>> while seq:
print ("{:>{z}}".format(' '.join(seq[0:row]), z=z))
del seq[0:row]
row += 1
1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54 55
56 57 58 59 60 61 62 63 64 65 66
67 68 69 70 71 72 73 74 75 76 77 78
79 80 81 82 83 84 85 86 87 88 89 90 91
92 93 94 95 96 97 98 99 100 101 102 103 104 105
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
>>>
We’re translating from one scope to another with the z
variable.