5
\$\begingroup\$

I have been working a number pyramid program. This is a question from Y. Daniel Laing's Introduction to programming using Python (which is based on Python 3.2). The question is from chapter 5, and it is number 5.19 in programming exercises portion of the chapter. The question is stated as follows:

Write a program that prompts the user to enter an integer from 1 to 15 and displays it as the following sample run:

I don't have the image, but it is something like this:

Enter the number of lines: 3

 1
 2 1 2
 3 2 1 2 3

The solution I have come up with is this:

p = eval(input("Enter the number of lines: ")) 
num = 0
y = 1
while num < p:
 y = num
 line = str(y+1) + " "
while y >= 1:
 y -= 1
 line += str(y+1) + " "
while y < num:
 line += str(y + 2) + " "
 y +=1
print(format(line, "^80s")) 
num +=1

If anyone has a better solution that would be simpler, please let me know.

200_success
146k22 gold badges190 silver badges479 bronze badges
asked Oct 1, 2013 at 1:30
\$\endgroup\$
1
  • 2
    \$\begingroup\$ But that's not a working code at all. It will just get infinitely stuck at the first loop. \$\endgroup\$ Commented Oct 1, 2013 at 6:44

4 Answers 4

4
\$\begingroup\$

Like 200_success said, the key is in thinking at the higher level. But I think his approach can be simplified.

Lets first define a row function, which simply calculates a list of numbers in an n'th row of our output:

# When n=3, returns [3, 2, 1, 2, 3]
def row(n):
 return list(reversed(range(2, n+1))) + list(range(1, n+1))

And now we can use this to print out the lines:

for n in range(1, 5):
 print(row(n))

Giving us the following output:

[1]
[2, 1, 2]
[3, 2, 1, 2, 3]
[4, 3, 2, 1, 2, 3, 4]

The core of the problem is now solved. The only thing left is formatting. For this we can write another function, which formats each number in list into a three-character box (with "%3s"), and also appends a certain amount of padding to make sure lines are aligned like a pyramid:

def formatted_row(n, num_rows):
 padding = ' ' * (num_rows-n)
 return padding + ''.join(["%3s" % x for x in row(n)])

Now we're almost there. Just need to tie it all together:

# When n=3, returns [3, 2, 1, 2, 3]
def row(n):
 return list(reversed(range(2, n+1))) + list(range(1, n+1))
def formatted_row(n, num_rows):
 padding = ' ' * (num_rows-n)
 return padding + ''.join(["%3s" % x for x in row(n)])
num_lines = eval(input("Enter the number of lines: "))
for n in range(1, num_lines+1):
 print(formatted_row(n, num_lines))
answered Oct 1, 2013 at 7:36
\$\endgroup\$
2
\$\begingroup\$

Another high-level of thinking about pyramid is as of matrix:

f(1, -n) f(1, -n+1) ... f(1, -1) f(1, 0) f(1, 1) ... f(1, n)
f(2, -n) ... f(2, -1) f(2, 0) f(2, 1) ... f(2, n)
... ... ...
f(n, -n) ... f(n, 0) ... f(n, n)

Where some of f(x, y) is numbers and some are just spaces. Note, how I chose to index columns from -n to n instead of from 0, this will make our code simpler. Given all that, it's trivial to write f():

def f(line, place):
 # number is just an offset from center + 1
 number = abs(place) + 1
 # don't display numbers greater than line number
 return str(number) if number <= line else ' '

Now we only need to go for all lines from 1 to pyramid height and display a row of f() values joined with ' ':

def pyramid(height):
 # same indexes for each line, so we'll reuse them
 places = range(-height+1, height)
 for line in range(1, height+1):
 print ' '.join(f(line, place) for place in places)

As an added bonus we can trivially prevent pyramid from skewing for numbers> 9 by changing last line in f() to:

 return str(number) if number <= line else ' ' * len(str(number))
answered Feb 16, 2015 at 5:52
\$\endgroup\$
1
\$\begingroup\$

This feels like a C program. Python can be a lot more compact, and more importantly, expressive. The key is to think at a higher level than a few characters at a time. List comprehensions help a lot.

Each row consists of a countdown, a "1" in the middle, then an ascending count. Let's work on the right half first. We can generate the ascending count using range(). We have to format them all into a fixed width column. Then we concatenate the mirror-image of the right half, the middle "1", and the right half.

def pyramid(height):
 FMT = '%3s'
 def row(r):
 right_half = [FMT % num for num in range(2, 2 + r)] + \
 [FMT % ' ' for spc in range(2 + r, 1 + height)]
 return ''.join(list(reversed(right_half)) + # Mirrored right half
 [FMT % 1] + # Center
 right_half) # Right half
 return "\n".join([row(r) for r in range(height)])
print(pyramid(p))
answered Oct 1, 2013 at 4:04
\$\endgroup\$
1
  • \$\begingroup\$ Wow Half of what you guys just wrote we haven't even touched on, I really think they should reconstruct this book because I am finding that a lot of the higher functions can be used in these exercises and yet they haven't even mentioned them, as for the formatting yeah this book only gives about 5 options. \$\endgroup\$ Commented Oct 3, 2013 at 13:54
-3
\$\begingroup\$

Agree, the first block definitely puts you in an infinite loop. Also the three while loops don't make it clear what you are doing - better to break up the padding from the pyramid construction.

I'm also working from Yang's book. This challenge in Ch.5 assumes no knowledge of functions but the above got me close to a solution with this:

lines = input("enter the number of lines")
lines = int(lines)
count = 1
while count < lines+1:
 padding = ' '*(lines-count)
 digits = list(range(1,count+1))
 output = padding + str(digits[::-1]) + str(digits[1:])
 print(output)
 count+=1
answered Jul 26, 2017 at 6:46
\$\endgroup\$
2
  • \$\begingroup\$ Welcome to Code Review! A good answer should be about the code in the question. Please explain what you did differently and why it is better than the posted code. See also How to Answer \$\endgroup\$ Commented Jul 26, 2017 at 7:40
  • \$\begingroup\$ We are looking for answers that provide insightful observations about the code in the question. Answers that consist of independent solutions with no justification do not constitute a code review, and may be removed. \$\endgroup\$ Commented Jul 26, 2017 at 12:02

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.