Flip a graph

Terry Reedy tjreedy at udel.edu
Sat Jan 4 16:57:49 EST 2014


On 1/4/2014 11:15 AM, Jason Friedman wrote:
> I am teaching Python to a class of six-graders as part of an
> after-school enrichment.

Great. I love seeing basic Python used for that sort of thing.

>  These are average students.  We wrote a
> non-GUI "rocket lander" program:  you have a rocket some distance above
> the ground, a limited amount of fuel and a limited burn rate, and the
> goal is to have the rocket touch the ground below some threshold velocity.
>
> I thought it would be neat, after a game completes, to print a graph
> showing the descent.
>
> Given these measurements:
> measurement_dict = { # time, height
>      0: 10,
>      1: 9,
>      2: 9,
>      3: 8,
>      4: 8,
>      5: 7,
>      6: 6,
>      7: 4,
>      8: 5,
>      9: 3,
>      10: 2,
>      11: 1,
>      12: 0,
> }
>
> The easiest solution is to have the Y axis be time and the X axis
> distance from the ground, and the code would be:
>
> for t, y in measurement_dict.items():
>      print("X" * y)
>
> That output is not especially intuitive, though.  A better visual would
> be an X axis of time and Y axis of distance:
>
> max_height = max(measurement_dict.values())
> max_time = max(measurement_dict.keys())
> for height in range(max_height, 0, -1):
>      row = list(" " * max_time)
>      for t, y in measurement_dict.items():
>          if y >= height:
>              row[t] = 'X'
>      print("".join(row))
>
> My concern is whether the average 11-year-old will be able to follow
> such logic.  Is there a better approach?

I would take a black and white 'canvas' (rectangular array of printable 
blocks) approach. First, separate creating the plot (output) and 
printing it. (If nothing else, this allows easy automatic testing of the 
output without capturing print output.)

plot = []
for t, y in measurement_dict.items():
     plot[t] = "X" * y

def printplot(plot):
   for row in plot:
     print(row)

printplot(plot)

The plot loop could be a list comprehension, but I assume you are not 
doing those. Next, I would modify the plot loop to make a rectangular array.

max_height = max(measurement_dict.values())
...plot[t] = "X" * y + ' ' * max_height - y

Then transpose the array either with zip or an explicit double loop and 
print it with the rows reversed. Example:

plot = ['xxxx', 'xx  ', 'x    ']

def printplot(plot):
   for row in plot:
     if not isinstance(row, str):
        row = ''.join(row)
     print(row)

printplot(plot)
print()
printplot(reversed(list(zip(*plot))))
 >>>
xxxx
xx
x

x
x
xx
xxx

Or start with a list of lists of chars (blank canvas) and fill in 'x's 
column by column.

-- 
Terry Jan Reedy




More information about the Python-list mailing list