Assignment 5
Decisions, Decisions
Pair programming for this lab and assignment, with a partner who you did not work with on the last Alice assignment.
The primary purpose of this lab and assignment is to practice making practical use of a number of conditional statements in the context of Reeborg programming and programs with textual input and output.
In Lab
In RUR-PLE Lesson 15, do the Weeding and seeding time exercise, using the en_harvest4.wld world file. In this world, Reeborg starts with 99 carrots (beepers).
After at most 40 minutes, move on to the second program in this lab, even if you haven't finished this one. The en_harvest4a.rur file that comes with RUR-PLE is a solution, but try develop your own. You need to be comfortable with this exercise before moving on to the Reeborg part of the following assignment.
At the bottom of the lessons table of contents there is a link to a Summary of instructions. Only the first three sections, Reeborg's actions, Tests, and Special built-in function are of use in this course.
Read the beginning of the Wikipedia article on the quadratic equation, up to the last bullet in the "Discriminant" section (less than a page of text).
Don't panic. This should be review for some, but if you are not comfortable with this level of mathematics, that's Ok. You only need to be able to translate a few of these equations into Python for this lab exercise. You don't need to understand their significance, such as the relation to the graphs on the Wikipedia page. This is the most mathematical this course will get, and no assignment or test question will be nearly this mathematical. (We live in a world of huge complexitly. Thus working with computers often means reading documentation much of which you don't understand, and don't need to understand. You develop confidence in your ability to extract what you need and move on.)
From now on you will often be asked (in tests, labs, assignments, practice and review problems, and class exercises) to complete skeletal programs. For the rules of this game, visit the Practice and Review page and read from the paragraph "Starting in week 5..." paragraph to the end.
Here's the program to complete in this lab:
# lab5.py, by chaynes@indiana.edu
import math
def discriminant(a, b, c):
#...
def quadratic_solution(a, b, c):
"""
Given the quadratic coefficients a, b, and c, print one of three messages
indicating the single root, the two real roots, or that the roots are
imaginary.
>>> quadratic_solution(5, 2, 3)
The roots are imaginary
>>> quadratic_solution(0, 0, 3)
There are no roots
>>> quadratic_solution(0, 0, 0)
Any value is a root
>>> quadratic_solution(0, 2, 1.2)
The root is -0.6
>>> quadratic_solution(1, 2, 1)
The root is -1.0
>>> quadratic_solution(1, 8, 3)
The roots are -0.394448724536 and -7.60555127546
>>>
"""
if a == 0:
#.
#.
#.
#.
#.
#.
#.
else:
d = discriminant(a, b, c)
#.
#.
#.
#.
#.
#.
#.
#.
def main():
"""
Prompt for the quadratic equation coefficents and
pass them to the quadratic_solutions function.
"""
a = float(raw_input('Quadratic coefficient: '))
b = float(raw_input('Linear coefficient: '))
c = float(raw_input('Constant coefficent: '))
quadratic_solution(a, b, c)
if __name__ == '__main__':
main()
Get started by cutting and pasting this program skeleton into a new RUR-PLE or IDLE program window.
This program handles the "degenerate" cases when a is 0, which are not considered in the Wikipedia article. As you can see from the test cases in the quadratic_solution documentation comment, when both a and b are 0, the message There are no roots is printed, unless c is also 0, in which case another appropriate message is printed. And if a is 0 and b is not, then a little algebra proves root is minus c divided (floating division!) by b. Can you see what would happen if these special 0 cases were not considered and the basic quadratic equation formulas were used? Give it a try.
When a is not zero (we have a real quadratic equation), the discriminant is calculated. As you can also see from the test cases, there are three separate cases: when the discriminate is greater than, less than, and equal to zero.
Remember that it helps a lot to write your program a bit at a time, testing your code at every opportunity.
At least once, when you have a bit of interaction working with RUR-PLE or IDLE, try running your program from the operating system shell. Just follow the following simple steps:
- Open a Windows cmd (command shell) window by executign Start > Run > cmd.
- Change the shell's working directory to a directory in which your program file is stored. One easy way to do this is to run the command cd Desktop and save your program on the desktop (unless it is already there).
- Run your program with the command python lab5.py.
As usual before the lab is over, submit your lab work via our Oncourse Assignment tool (whether your program is finished or not). Be sure both partner's names and usernames are on the first-line comment, as always for pair work, or you won't both get lab credit.
Please also be sure before leaving lab that you understand the assignment. And start work on it early. You can never tell how long it will take to finish a program until it works, and you may need to go to the peer tutoring session, office hours, or make other arrangements to get face-to-face help, which is probably not possible on Wednesday or Thursday, unless you can make Wednesday office hours. Email is often not a suitable way of expressing a programming problem or learning where you got stuck.
Lab solutions, and a solution to the last Python assignment, are posted using the Oncourse resources tool before Monday noon. (If I should ever fail at this or make any other mistake in managing the course web, please send me email!) You are always encouraged to look at these solutions, even if you think your solution was fine. And of course there are many possible solutions to almost any programming problem, so if your solution is different it could be fine also. Please ask if you are in doubt. Also consider whether the style of your solution compares favorably, even if it is correct.
Assignment
There are two programs in this assignment, the first programming Reeborg and the second is a game with a textual user interface.
The RUR-PLE Weeding and seeding time exercise you did in lab assumes that Reeborg has a bag full of carrots to begin with. That isn't strictly necessary for the test world, since it contains enough carrots to fully plant the garden plot. However, if you eliminate the carrots in his bag to begin with (click the beeper button on the tool bar) and run the program, you get an error at the corner of street 1 and avenue 3, since he (or is it she?) tries to plant a carrot when he has none.
For this assignment, first modify the world so Reeborg starts with no carrots and save the new world. Next modify the en_harvest4a.rur program, or your lab solution, so that in the end no place has more than one carrot and as many as possible of the originally blank spots are planted. If all excess carrots have been collected (at corners with two carrots), Reeborg stops if he encounters a bare spot
Call the resulting program harvest5.rur. Your program should work with any world in which all the garden in which all the carrots (beepers) are planted is in streets 1 through 6 and rows 2 through 7, no intersection has more than two carrots (next week we'll learn how to handle any number), the only walls are on the edge of the world, and Reeborg is initially at the lower left facing east.
You will need to use the Reeborg function carries_beepers(), which returns True if Reeborg currently has at least one beeper in his bag and False otherwise.
This requires that Reeborg make two passes over the garden, but there are a few possible variations on just what those passes do. One of them is to pick up all excess carrots (more than one at an intersection) on the first pass, and then plant bare spots on the second pass. The following are the main changes to en_harvest4a.rur required to make implement this:
All but the turn_off() function calls after the definitions are making one pass over the garden. We need to make two passes and don't want to repeat these calls, so put them in the body of a new function called pass_over_field.
The original action performed at each intersection was one_carrot_only, but we now want to perform different actions on each pass this time. So replace this function definition with two new ones:
- at_most_one_carrot(): Reeborg picks up the second carrot if there is one, and otherwise does nothing (this is a simplification of one_carrot_only).
- plant_if_bare(): Reeborg does nothing unless at a bare spot (no carrots at the current intersection). Otherwise, if he has at least one carrot, he plants one, and otherwise he turns off.
Store the at_most_one_carrot function in a variable named action before the first pass, and store plant_if_bare in the variable before the second pass.
Replace all calls to at_most_one_carrot with calls to action.
Rename pick_and_move to action_and_move, and change the calls to this function accordingly, since the action does not involve picking on the second pass. (The program would work without this change, but it is bad style if function names are inconsistent with what they do.)
Note: when a function like pass_over_field needs to do different things each time it is called it is usually better style to abstract this difference with a parameter, rather than assigning a global variable, but in this case the use of the function repeat does not allow this (without knowing more of Python than we do now).
Next develop a program that behaves as described below and illustrated in the following operating system shell transcript:
C:\home\201\src>python rps_game.py Your play [enter "rock", "paper", "scissors", or "quit"]: paper You win Your play [enter "rock", "paper", "scissors", or "quit"]: scissors You loose Your play [enter "rock", "paper", "scissors", or "quit"]: scissors You win Your play [enter "rock", "paper", "scissors", or "quit"]: rock It's a draw Your play [enter "rock", "paper", "scissors", or "quit"]: papr Error: bad play Your play [enter "rock", "paper", "scissors", or "quit"]: quit Score: 2 wins and 1 losses C:\home\201\src>
You'll find the rules of the game in the "Game play" section of the Wikipedia Rock, Paper, Scissors article. You might also enjoy reading some other fascinating parts of this article, such as the game's connection with mathematics and the mating strategies of certain lizards!
The user plays against the computer in this program, with the computer making a random choice between the three possible plays. This randomness means of course that it is most unlikely that your program will perform exactly as in the transcript above. You can get familiar with the game rules by figuring out which play the computer must have made for each of the game rounds in the transcript.
Here's a skeleton for the program:
# rps_game.py, by chaynes@indiana.edu
import random
def random_play():
"""Randomly return one of the strings 'rock', 'paper', or 'scissors'."""
#.
#.
#.
#.
#.
#.
#.
def winner(your_play, my_play):
"""
your_play and my_play are the strings 'rock', paper' or 'scissors'.
Return the string 'you', 'me', or 'draw', indicating the winner.
"""
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
def valid_play(play):
"""
Return a boolean value indicating if play is one of the string
'rock', 'paper', or 'scissors'.
"""
#.
def rock_paper_scissors():
"""
Repeatedly prompt for the user's move, generate a random opponent move, and
print the result of one play of the rock, paper, scissors game.
If the user enters "quit", then print the score and return.
See http://en.wikipedia.org/wiki/Rock,_Paper,_Scissors.
"""
wins = 0
losses = 0
while True:
prompt = 'Your play [enter "rock", "paper", "scissors", or "quit"]: '
your_play = raw_input(prompt)
if your_play == 'quit':
#...
#...
if valid_play(your_play):
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
#.
rock_paper_scissors()
Turn in your harvest5.rur and rps_game.py files via Oncourse as usual.
Don't forget that, as always with team work, only one team member may make the submission (preferably with the other watching) and the names of both team members should be in the comment on the first line of the program. There is a grade penalty for failing to follow these instructions.