Due Tuesday 26-Oct, at 10:00pm
Do not use try/except this week. The autograder (or a manual CA review later) will reject your submission entirely if you do.
Like in the previous assignment, we will be grading your code based on whether it follows the 15-112 style guide. We may deduct up to 10 points from your overall grade for style errors. We highly recommend that you try to write clean code with good style all along, rather than fixing your style issues at the end. Good style helps you code faster and with fewer bugs. It is totally worth it. In any case, style grading starts this week, so please use good style from now on!
for
loops or while
on the problems marked recursive.onlyEvenDigits([43, 23265, 17, 58344])
returns
[4, 226, 0, 844]
.
Also the function returns the empty list if the original list is empty.
Remember to not use strings.
This problem is designed to get you more practice with using dictionaries, processing strings and get you thinking about recursion. This homework has been adapted from the presentation of Eric Roberts for nifty assignments at SIGCSE 2013.
Even though this problem has some recursion, you are not limited by the recursion rules listed at the beginning of this handout. (Feel to use loops, iterative helper functions, etc.)
turtle
is a Python module that allows for drawing of simple figures. In order to use it, you give an imaginary on-screen turtle commands regarding where to go, and it draws a line along its path.
The details of turtle library can be found at http://docs.python.org/library/turtle.html
Consider the following very simple turtle program which makes use of some basic turtle functionality to draw two squares:
import turtle
turtle.pendown()
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.penup()
turtle.forward(100)
turtle.pendown()
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.penup()
turtle.forward(100)
(You should run this in Python and convince yourself you understand how it works.)
In order to simplify the usage of turtle, we have designed a new language for writing turtle programs. We call it Turtle Script. A Turtle Script program is specified as a string consisting of a sequence of commands. For example, consider the following Turtle Script program:
F120 L90 F120 L90 F120 L90 F120
This program moves the turtle in a square 120 pixels on a side, ending up in the same position and orientation as when it started, like so:
Turtle Script also includes the concept of repetition. If you enclose a sequence of commands in curly braces, you can repeat that entire sequence any number of times by preceding that block of commands with the letter X followed by the desired number of repetitions. The program to draw a square can therefore be simplified like this:
X4 {F120 L90}
In English pseudocode form, this program therefore has the following effect:
Repeat the following sequence of commands 4 times
Move forward 120 pixels.
Turn left 90 degrees.
Repetitions can be nested to any level. You could, for example, use the program:
X4 {X4 {F120 L90} L10}
to draw two squares with a 10-degree left turn in the middle.The figure after drawing these four squares looks like this:
Turtle Script also includes functions. You can define a function by enclosing the body of the function in braces and then preceding the braces with the command M followed by a single character name for the function. The following example shows a definition of a function called S that draws a square:
MS {F120 L90 F120 L90 F120 L90 F120 L90}
The keyword M specifies that the following is a function name, followed by function body enclosed in braces. Remember that the M command only defines a function but does not execute it. After this function has been defined, you can use the function name to call this function. Here is an example of defining a function and then calling it two times:
MS { X4 { L90 F50}} S U F100 D S
This program will create two squares in a single line separated by 50 pixels.
Command | Description |
---|---|
Fn |
Move the turtle forward by n pixels. If n is missing move by default value of 50 pixels. |
Ln |
Turn the turtle left by n degrees, where n defaults to 90 |
Rn |
Turn the turtle right by n degrees, where n defaults to 90 |
D |
Calls the pendown function from Turtle |
U |
Calls the penup function from Turtle |
Xn cmds |
Repeats the specified block of commands n times. |
MA cmds |
Defines a function A where A is any single character not already reserved. The function A consists of the commands specified in the block. A cannot be one of the other commands (F, L, R, D, U, X, or M). |
A |
Execute the function A. A is just a placeholder, you can use any character to define a function. A cannot be one of the other commands (F, L, R, D, U, X, or M). |
Here are the functions you should write while solving this problem.
tokenizeTurtleScript(program)
Write a function called tokenizeTurtleScript(program)
which, given a Turtle Script program, return a list of commands in that program. The function should break up the input string into individual commands and return a list containing commands as strings.
The most common kind of token in a turtle program is a command character (typically a letter, although any non-whitespace character is legal), which is typically followed by a sequence of decimal digits. For example, the command F120, which moves the turtle forward 120 pixels, is a single token in a turtle program. All command listed in the table above are individual tokens, including repetition and function definitions.
In addition, spaces are not required between tokens but are permitted for readability. These rules mean, for example, that you could rewrite the program that draws a square as:
F120L90F120L90F120L90F120
even though doing so makes the program much more difficult for people to read.
Consider the following examples:
tokenizeTurtleScript("F120L90F120L90F120L90F120") returns
['F120', 'L90', 'F120', 'L90', 'F120', 'L90', 'F120']
tokenizeTurtleScript("X4 {F120 L90} U F200 X4 {F120 L90}") returns
['X4{F120L90}', 'U', 'F200', 'X4{F120L90}']
tokenizeTurtleScript("MS { X4 { L90 F50}} S U F100 D S") returns
['MS{X4{L90F50}}', 'S', 'U', 'F100', 'D', 'S']
Note: This problem is made much easier if you plan ahead by choosing good helper functions.
convertTurtleScript(program, funcs)
Write a function convertTurtleScript(program, funcs)
that will convert a Turtle Script program to a Python program. It should take as arguments a Turtle Script program and a dictionary consisting of all the functions defined so far in the program. The dictionary will contain function names as keys and function code as values.
The convertTurtleScript function has the responsibility of taking the program and translating each token to the appropriate command for turtle in Python. For example, given the program tokens:
['F120', 'L90', 'F120', 'L90', 'F120', 'L90', 'F120']
The convertTurtleScript function will have to translate each token into the appropriate function call in Python. Thus, executing the F120
token needs to invoke the function call turtle.forward(120)
. Similarly, executing the L90
token needs to invoke a call to turtle.left(90)
Notes:
tokenizeTurtleScript
in order to convert the program to tokens, and then execute the tokens one at a time.funcs
argument that is passed to this function is a dictionary to map function names to function code. Recall that functions are defined as part of Turtle Script. Hence, as you are executing commands you will come across function definitions. When you do, add those functions to the funcs
dictionary. Later, if a function is being called, you can retrieve that function’s commands from the dictionary. For the initial call to convertTurtleScript
, you should just pass an empty dictionary.Consider the following examples.
First,
p = "F120 L90 F120 L90 F120 L90 F120"
funcs = dict()
convertTurtleScript(p, funcs)
will print out:
turtle.forward(120)
turtle.left(90)
turtle.forward(120)
turtle.left(90)
turtle.forward(120)
turtle.left(90)
turtle.forward(120)
Second,
p = "MS { X4 { L90 F50}} S U F100 D S"
funcs = dict()
convertTurtleScript(p, funcs)
will print out:
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.penup()
turtle.forward(100)
turtle.pendown()
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
turtle.left(90)
turtle.forward(50)
Important Note: convertTurtleScript
does not execute a Python turtle program. Instead, it prints one that a user could execute later.