I have to write a program in python that will take a number and print a right triangle attempting to use all numbers from 1 to that number. For example:
Enter number: 10
Output:
7 8 9 10
4 5 6
2 3
1
Enter number: 6
Output:
4 5 6
2 3
1
Enter number: 20
Output:
11 12 13 14 15
7 8 9 10
4 5 6
2 3
1
For which I have written the following function
def print_right_triangle(num):
c = 1
k = 0
l = []
while(k < num-1):
v = []
for i in range(c):
v.append(k+1)
k += 1
c += 1
if k > num:
break
l.append(v)
p = len(l)
for i in range(p):
for j in l[p-(i+1)]:
print(j, end=' ')
print()
return None
print_right_triangle(10)
It's giving the same output and solved my problem. I was wondering is there any more pythonic way to do this
-
2\$\begingroup\$ One liner with a bit of maths to find x(x+1)/2 = n: lambda x: [print(*range(1+i*~-i//2, 1+i*-~i//2)) for i in range(int(((1+8*x)**.5-1)/2), 0, -1)] \$\endgroup\$rak1507– rak15072021年11月19日 11:43:43 +00:00Commented Nov 19, 2021 at 11:43
-
\$\begingroup\$ @rak1507 Thank you so much!!! \$\endgroup\$coderina– coderina2021年11月19日 13:27:37 +00:00Commented Nov 19, 2021 at 13:27
-
\$\begingroup\$ @rak1507 could you please explain 1+i*~-i//2 this, its so tricky to understand this \$\endgroup\$coderina– coderina2021年11月19日 14:14:34 +00:00Commented Nov 19, 2021 at 14:14
-
1\$\begingroup\$ ~-i is magic for (i-1) so it's 1 + i * (i-1) // 2 (sorry: code golfing habits die hard) \$\endgroup\$rak1507– rak15072021年11月19日 14:38:39 +00:00Commented Nov 19, 2021 at 14:38
-
\$\begingroup\$ @rak1507 ohhokay....got it..thank you so much for responding! \$\endgroup\$coderina– coderina2021年11月19日 18:54:55 +00:00Commented Nov 19, 2021 at 18:54
1 Answer 1
Optimized != pythonic
Optimized means "spending less resources". "Pythonic" means "using idiomatic Python features". Sometimes they come together, sometimes don't. Pythonic code is clean and maintainable, while optimized can be very unclear and need many comments.
Anyway, optimization should start with making the code readable, and pythonic code should be readable.
Make more use of Python features
List comprehensions, range arguments and unpacking can be very handy. This code
v = []
for i in range(c):
v.append(k+1)
k += 1
is clearly just a
v = [k+1+i for i in range(c)]
k += c
and, changing the range arguments,
v = list(range(k+1, k+c))
k += c
And this code
for j in l[p-(i+1)]:
print(j, end=' ')
print()
can be written as
print(*l[p-(i+1)])
and
p = len(l)
for i in range(p):
print(*l[p-(i+1)])
is walking the l
list backwards, so it's
for line in reversed(l):
print(*line)
This is pythonic.
Optimizations
Change the algorithm. Here you're gathering all the number in a list to output them. But the numbers are all in order, so you can easily avoid lists at all - just make loops with print
s.
First, read some theory.
Now you know that only numbers that equal n*(n+1)/2
can be used to build such triangles. You can solve n*(n+1)/2 = num
as a quadratic equation and round n down to get the number of lines without loops like rak1507 did.
Next, find formulas for starting and ending numbers in each line to put them into range arguments.
And now you can code it in three lines.
-
\$\begingroup\$ Thank you so much!! for this wonderful explaination \$\endgroup\$coderina– coderina2021年11月19日 13:27:19 +00:00Commented Nov 19, 2021 at 13:27