math
moduleIn our lab we will use Turtle to draw images. But that kind of graphical output can be awkward in programs that are designed to be automated and thus have text-based interfaces (like a lot of scientific software). In those contexts, we can use text for visualization (often termed ASCII art). Today we will use loops to generate some text-based visualizations (Adapted from “CS for All”), including of a Sine wave!
As a starting point, let’s write functions to print a rectangle and a “lower” right triangle. For print_rect
, the parameters will be the width
, the height
and the character and for print_triangle
, the parameters will be the size
(width and height) and the character.
>>> print_rect(4, 6, "%")
% % % %
% % % %
% % % %
% % % %
% % % %
% % % %
>>> print_triangle(3, "@")
@
@ @
@ @ @
One restriction is that you are not allowed you to use the string multiplication operator (the goal is to practice using loops). As a hint, the print
function adds a new line (carriage return) at the end by default. We can override that default by changing the end
argument (we will learn more about these default arguments later in the semester). For example, notice the different output from these two code snippets (the semicolon just allows us to have multiple Python statements on one line).
>>> print("%", end = " "); print("%", end = " ");
% %
>>> print("%"); print("%");
%
%
Recall our discussion of syntax vs. semantics. Before we write any code let’s figure out the semantic tools we will use. Some questions for us to answer:
Try implementing both functions before peeking at the code.
def print_rect(width, height, char):
"""Print an ASCII rectangle
Args:
width, height: Width in characters, height in rows of rectangle
char: Character to print
"""
for i in range(height):
for j in range(width):
print(char, end=" ")
print() # Go to a new line at end of the row
def print_triangle(size, char):
"""Print an ASCII lower triangle
Args:
size: Height in rows and with in characters of triangle
char: Character to print
"""
for i in range(size):
for j in range(i+1):
print(char, end=" ")
print()
Imagine you want to plot a sine wave using a similar text rendering, where the rows are the angle and width is the amplitude. That is we want to implement the following, where the parameters are the height, the width, the character and the degrees-per-row.
>>> print_sin(10, 10, "*", 45)
*
*
*
*
*
*
*
*
*
*
Again before we start, what semantic tools will we need? Loops (like before) and a way to calculate Sine. Not surprisingly Python has a built-in sin function. Is the input for that function degrees or radians (or both)? And would we find that out? If it is radians, how could we convert from degrees to radians?
We always want to work incrementally (testing as a we go). How could we decompose this large problem into a set of smaller steps? Show a potential set of steps…
math.sin
will produce a float
in the range [-1,1], but we need an integer number of columns in the approximate range [0,width
]).Now lets work through those steps to implement print_sin
. Show a possible solution…
def print_sin(width, height, char, degrees_per_row):
"""Print a sine wave (with angle on the vertical)
Args:
width: Maximum approximate width in characters
height: Height in rows
char: Character to print sine value
degrees_per_row: Increment in angle for each row
"""
degrees = 0
for i in range(height):
amplitude = math.sin(math.radians(degrees))
# Map [-1,1] to width
current_width = amplitude * (width / 2) + (width / 2)
for j in range(int(current_width)):
print(" ", end=" ")
print(char)
degrees += degrees_per_row # The same as degrees = degrees + degrees_per_row