**Homework 1: Scripting** **Reed CSCI 121 Spring 2025**   *submit by 2/4 at 9am* In lecture we covered some key elements of the Python language. We looked briefly at some kinds of calculations you can perform on data. We showed how you can keep track of computed values with variables by assigning a variable a value that you ask Python to compute. We can interact with Python's interpreter (the `python3` command) to perform these computations. Or else we can have the Python interpreter run a script we've written to have it perform a sequence of calculations we've programmed. We also started thinking a little about the different kinds, or *types*, of data values manipulated in Python programs. For numeric calculations we played with both floating point data and integer data. These data values have the type `float` and the type `int`, respectively. You also learned how to manage text information using *string* data. Strings are text character sequences and have the Python type `str`. You can check this type info in the Python interpreter as shown below: ~~~python >>> type(3) >>> type(3.14) >>> type("Is it confusing that three is 3 and also 3.0?") >>> type('Or did I mean "three" there?') ~~~ As we continue the semester, and as you read and learn more about Python, you'll recognize that Python can often be flexible about programs' use of different types of data. Nevertheless, to be a good programmer, you'll often want to be deliberate about what types of data you are working with in a program, and take care in not mixing these different types up. In this lab homework we're going to practice programming using the kinds of calculations you've learned so far. Below are eight Python exercises. Each asks you to write a simple *interactive* script that can be run in the terminal. Python allows you to read what's entered into the terminal (using `input`) and to report computed values (using `print`). Below, for example, is a short three-line script that performs temperature unit conversion, getting a temperature in degrees Celsius, then reporting the equivalent in degrees Fahrenheit: ~~~python c = float(input("Temperature in degrees Celsius? ")) f = (c * 9.0 / 5.0) + 32.0 print(f) ~~~ Running the code, we see that `input` produces a prompt, then waits for the user to enter a value. Python reads their entry as a string of characters, and so we use `float` to convert those characters to a floating-point numeric value. The second line, a variable assignment to `f` using the value `c`, computes the floating point value according to that calculation. The value of variable `f` gets printed because of the last line of the script. Here's what happens in Terminal when we run that code using the `python3` command and, say, enter `100.0`: ~~~none C02MX1KLFH04:hw01 jimfix$ python3 temperature.py Temperature in degrees Celsius? 100.0 212.0 ~~~ It's possible to make the output of `print` more readable by including other text in that line of output. To do this, we can explictly convert the temperature to a string of characters using the `str` conversion function and then append strings around that formatted information. We append strings using the `+` operator. For example, if we change the last line of the code above to ~~~python c = float(input("Temperature in degrees Celsius? ")) f = (c * 9.0 / 5.0) + 32.0 print("That is "+str(f)+" in degrees Fahrenheit.") ~~~ it leads to this interaction ~~~none C02MX1KLFH04:hw01 jimfix$ python3 temperature.py Temperature in degrees Celsius? 100.0 That is 212.0 in degrees Fahrenheit. ~~~ Note the spaces that we used to separate the number from the other text of the sentence. Each of the exercises below asks you to write a Python script similar to the one above. Each program you write takes an input, or a series of inputs. It then performs calculations on that input data and produces a formatted output of those calculations' results. We first ask you to work with strings alone. You then work with integer and floating point values. For these you'll want to convert input strings into numbers using the `int` and `float` functions. # Submission and Autograding You should run your scripts several times, and with different inputs, to make sure that your code is working. Once you have reasonable confidence that it is working, submit it at the appropriate assignment link on [the Gradescope site for this course](https://www.gradescope.com/courses/432033). When you upload the file for that problem on Gradescope we'll immediately run a series of tests on that code to see if it is correct. Within a minute or so, you'll get feedback from our `aga` Gradescope autograder" as a series of messages. If all these tests pass, then these messages will be green. Any failed tests will give a red message, and usually with some extra information underneath that can help you figure out what we found wrong with the code. Our ability to give feedback in this way is limited, so you should seek help from your instructor or a tutor to help you explain what went wrong, and to help you think about fixing the problem. On some rare occasions some of you may face something that's wrong with our set-up so it's helpful to reach out to us if you are confused by the autograder's report. There will be those moments when there's something we didn't anticipate in your submission, hopefully rarely. Do not use Gradescope to test your code. Instead run the code yourself using Python's interpreter and only submit once you're convinced that the code is correct. If you fail some of our tests that should give you some pause. Take a moment to carefully look through your code and fix it, and then run some of your own tests before submitting it again. Don't just make a quick change, cross your fingers, and submit it again. **Scoring** Each problem is worth 20 points. 10 of those points are assigned by the auto-grader, and the remaining 10 will be assigned later by one of us and is our way of giving you (human) feedback on the quality of your code. The auto-graded score is determined by some thoughtful test inputs that we've devised to check different scenarios. Our use of automated testing is meant to mimic real-world software coding, where a programmer's code has to work in practice, sometimes facing unanticipated but perfectly reasonable scenarios. The hand-graded score reflects our sense of your coding. Was it clear and succinct? Or did it do something unusual just to get the tests to pass? When we get to more complicated coding, these points will help us give feedback on code "style." Making complicated code human-readable and human-understandable is often as important as whether the code works, especially for larger coding projects. We split the auto-graded score into two components. We give points for passing some of the tests. This helps us to at least see the progress you've made in tackling the problem. This will be especially valuable for later assignments when you've figured out most of the problem but maybe haven't considered some tricky “edge cases” yet. Both the test score and the hand-graded score allow us to reward you for figuring out most, if not all, of the problem's puzzle. And the hand-grading allows us to give feedback on the quality of your code. # Exercises • **[Hw1 Ex1] temperature** I've written a simple interactive script, downloadable [**as this linked file**](homework1/temperature.py) called `temperature.py` that requests an input, a numeric value that will be treated as a temperature in degrees Celsius. The program, after that amount is entered, reports the equivalent temperature in degrees Fahrenheit. Here is the Python code for that program: ~~~ python c = float(input("Temperature in degrees Celsius? ")) f = (c * 9.0 / 5.0) + 32.0 print("That is "+str(f)+" in degrees Fahrenheit.") ~~~ And here is an example of its execution in terminal: ~~~ none C02MX1KLFH04:homework1 jimfix$ python3 temperature.py Temperature in degrees Celsius? 40.5 That is 104.9 in degrees Fahrenheit. ~~~ The program takes a string as input and, assuming that its user types in a valid number, converts that string to a floating point value (with the `float(•)` conversion we described in lecture). It uses the variable `c` to store that value. It then assigns the variable `f` to the appropriate number of degrees, according to the Celsius-to-Fahrenheit formula. It then outputs that amount, but has to do so by converting the floating point value held in `f` to a string (with the `str(•)` conversion we also described in lecture). Modify the code so that it instead asks for a temperature in degrees Fahrenheit and reports the equivalent in degrees Celsius. Your program should lead to interactions like this one: ~~~ none C02MX1KLFH04:homework1 jimfix$ python3 temperature.py Temperature in degrees Fahrenheit? 104.9 That is 40.5 in degrees Celsius. ~~~ Note that you will first need to figure out what the relevant formula is that does the conversion in the opposite direction. Also, these are floating point operations. That means that there can be very slight rounding errors. For example, there is code that will give an output of 40.50000001 for the interaction above. In code that was interacting with a real user, you would probably want to round answers to prevent that sort of thing, but for this problem just give the answer your formula computes. We'll check that your output is similar enough in value to the number we expect. While the number you report only needs to be close enough, you need to get the spacing exactly right for the code to be considered correct --- • **[Hw1 Ex2] distance** We're writing a new app that allows people in Portland to find where they are relative to Reed's campus, one that presents a map to the app's user. The center of Eliot Circle is the origin of the map. When a person is walking around, the app gives a two-dimensional coordinate of their location, $(x,y)$, giving them a position within a grid laid over the map. The $x$ coordinate indicates how many miles east of Eliot Circle they are. The $y$ cordinate indicates how many miles north of Eliot Circle they are. At any moment, the app tells them their distance from Eliot Circle, and that is computed (using the Pythagorean Theorem) to be $$\sqrt{x^2 + y^2}$$ that is, the square root of the sum of the square of the distance east with the square of the distance north. We want to enhance the app so that it allows a student to figure out their distance from a classroom. If they are located at $(x_1,y_1)$ and the classroom is located at $(x_2,y_2)$, then their distance from that classroom is $$\sqrt{(x_2 - x_1)^2 + (y_2 - y_1)^2}$$ Write a Python script `distance.py` that allows you to experiment with this distance calculation. It should take the $x$ and $y$ coordinates of one location, and then the $x$ and $y$ coordinates of a second location. It should then report the distance using the above calculation. ~~~ none Location x-coordinate? 3.2 Location y-coordinate? 1.5 Classroom x-coordinate? 6.2 Classroom y-coordinate? -2.5 Distance: 5.0 ~~~ Note that you can compute the square root by using the exponentiation operator `**` and with an exponent of `0.5`. It's also possible to `import` Python's `math` package which defines a function `sqrt`. Either is fine, one requires that you practice using `import`. To import, put this line at the very top of the code, before the script that does the work: ~~~ python from math import sqrt ~~~ and then any code below that line will know about the function `sqrt`. ---- • **[Hw1 Ex3] hal** In the science fiction movie *2001: A Space Odyssey*, the artificial intelligence of the `HAL 9000` computer, when commanded to do something, tells the main astronaut character: ~~~ none I'm sorry, Dave. I'm afraid I can't do that. ~~~ Write a Python script `hal.py` that replicates this interaction. It should prompt for a name to be entered, and then take a string as input. It should then prompt for an action it should take, and then take a second string as input. Having obtained those two input strings, your program should then output a contrarian's reply using that name, and then report that the action was not taken. Here, for example, is a transcript from a terminal execution of the command `python3 hal.py`: ~~~ none What is your name? Dave Ok. Now enter an action: Open the pod bay doors. I'm sorry, Dave. I'm afraid I can't do that. (The action "Open the pod bay doors." was not performed.) ~~~ In that example, the first two lines are each a combination of a printed prompt (each ending with a space character) followed by the characters entered by the person running the program. Here, they entered `Dave` and hit the `[return]` key and then `Open the pod bay doors.` followed by the `[return]` key. After these two entries, a blank line and then the next two lines are printed by the script. Here is another example of an expected interaction with your program when run: ~~~ none What is your name? stanley kubrick Ok. Now enter an action: cut!!! I'm sorry, stanley kubrick. I'm afraid I can't do that. (The action "cut!!!" was not performed.) ~~~ Your program's interactions must exactly mimic the examples above. There should be a space between each prompt and the program user's input. There should be one space before the name and a period immediately following it. There should be a double quote character just before and just after the action. Note that, even though the document you are reading (this one here) might make it appear so, there should be no spaces at the start of each line. The lines are each left justified. Note that you can output a blank line with the python statement ~~~ print() ~~~ that is, by giving `print` no argument within the parentheses. Do your best to test your code and check the output, comparing it with our expected output. Be wary of your spacing before you submit. The interaction's transcript is in a fixed-width (i.e. monospaced or "typewriter") font, so each character, including spaces, appears in its own column. This means that the output characters can be seen to line up within a grid as depicted below: ![*Figure.* Gridding of terminal output.](images/hal-grid.gif) Now, with all that being said, get that AI working! (Or, I suppose, get it *not working*--- HAL is *stubborn* and unwilling to do anything.) **Tips** A big issue here is that there are two ways to describe a string of characters in Python. For example printing a `Hello.` line can be expressed in a program as ~~~python print("Hello.") ~~~ using double quotes around the string of characters and also instead using single quotes with ~~~python print('Hello.') ~~~ But this means that the single quote character `'` and the double quote character `"` have special meaning in this code. So, for example, you have to do extra work if you literally want a quote within a string. For example, `Don't.` could be expressed in two ways: ~~~python print("Don't.") print('Don\'t.') ~~~ The second form uses the "escape" backslash character `\ ` to alert Python that a special character is coming next. So we read `\'` as "escape to quote" There is also `\\ ` for "escape to backslash", `\t` for "escape to tab", and `\n` for embedding an escaped request to start a new line within the middle string. --- • **[Hw1 Ex4] marquee** Write a Python program `marquee.py` that attempts to mimic movie theater marquee signs, putting a word "*in lights*". To get an idea of what we want, below is an execution of the program: ~~~ none Title? hello ********* * hello * ********* ~~~ The first line is the input prompt, along with an entry of the word `hello`. The second output line is just a blank line. The next three lines show the word decorated with surrounding asterisks. Here are two other interactions: ~~~ none Title? Groundhog Day ***************** * Groundhog Day * ***************** ~~~ ~~~ none Title? Hello World: A Text-Based Adventure *************************************** * Hello World: A Text-Based Adventure * *************************************** ~~~ To do this you need to use some string operations. We've been using string concatenation, designated with the `+` plus sign above. Recall also that the `*` asterisk can be used for string repetition. For example, the expression `'hi'*5` means `'hihihihihi'`. Here are some other examples of string repetition in Python: ~~~ python >>> 'hi'*2 'hihi' >>> 'hi'*0 '' >>> 'hello ' + ('hey ' * 3) + 'bye' 'hello hey hey hey bye' ~~~ The other string operation you need is a function that computes the length of a string, `len`. It gives the number of characters in the string's sequence. Here are some example uses of `len`: ~~~ >>> len('hello') 5 >>> len('Hello, I must be going.') 23 ~~~ Note that it counts each space, each letter, and each punctuation mark laid out between the quotes. String concatenation, repetition, and length should be enough tools needed to make `marquee.py`. --- • **[Hw1 Ex5] toonies** You decide to visit Canada to do some shopping. You've become fond of their one-dollar coin, called a *loonie* because its backside depicts a common loon. You are even more fond of their two-dollar coin called a *toonie*. You like the toonie so much, you decide to pay for everything using these two-dollar coins. Devise a Python script that, when given an item's cost in Canadian dollars, expresses how many toonies you need to pay for that item. Your script should have this kind of interaction: ~~~none terminal:homework reeduser$ python3 toonies.py Item cost in Canadian dollars? 21 Pay 11 toonies. terminal:homework reeduser$ python3 toonies.py Item cost in Canadian dollars? 20 Pay 10 toonies. ~~~ You can assume that the item's price is a whole dollar amount and at least three dollars. (This means that you'll never calculate payments of fewer than two toonies.) **Note (and hint):** You should only be using integer calculations for this script. (No need for floating point!) And you shouldn't use any kind of Python conditional statement or conditional expression to write this code. (We'll be learning about those later in the course.) Instead, since we are interested in the evenness and oddness of the payment amount, you want to consider the amount's divisibility by two. --- • **[Hw1 Ex6] tipping** You've just eaten a tasty meal at a restaurant and you've decided to reward them for their service. Devise a tool that computes a tip amount. Your `tip.py` script should take three inputs: the meal's price in dollars and cents, along with a tip percentage from 0 to 100. Have it compute the tip as a floating point value and output that value, like so ~~~none terminal:hw1 jfix$ python3 tip.py Price dollars? 20 Price cents? 0 Tip percentage [0-100]? 15 3.0 terminal:hw1 jfix$ python3 tip.py Price dollars? 3 Price cents? 60 Tip percentage [0-100]? 50 1.8 terminal:hw1 jfix$ python3 tip.py Price dollars? 3 Price cents? 60 Tip percentage [0-100]? 20 0.72 ~~~ You can assume that the dollars, cents, and tip percentage are all integers. The dollar amount you output should be a floating point value. **Note:** In the last tip percentage example, suppose we only tipped 1 percent. Then the tip amount would only be 0.036, and that includes a fraction of a cent (3/5-th of a cent). Your code will be accepted as correct if the tip amount you output is within one cent of the exact amount, including fractions of a cent. This means that you are welcome to output an amount that *does not* have more than two digits after the decimal point. To do this, you could use Python's built in `round` function. This function can take two parameters and is documented [**here**](https://docs.python.org/3/library/functions.html#round). --- • **[Hw1 Ex7] menu** A friend in the restaurant business has asked you to develop a Python script for typesetting menus for his restaurants. Below is one he produced by hand on a typewriter for his fancy bistro called "Bobby's": ~~~none Bobby's Entrees --------------- Pasta verde.........................$ 15 Filet mignon w/ lobster and caviar..$107 Hamburger with fries................$ 9 ~~~ The menu has a top line with the restaurant name and `"Entrees"` underlined by dashes, and these lines are followed by the three entree lines with their prices. Write a script `menu.py` that produces these menus as output. It should take the restaurant name as input, and then it should take three input strings for the names of three different entrees, along with their prices in whole dollars. Each menu that your program outputs is 5 lines long. Here is a sample interaction: ~~~none Restaurant name? Bobby's First entree? Pasta verde First entree price? 15 Second entree? Filet mignon w/ lobster and caviar Second entree price? 107 Third entree? Hamburger with fries Third entree price? 9 Bobby's Entrees --------------- Pasta verde.........................$ 15 Filet mignon w/ lobster and caviar..$107 Hamburger with fries................$ 9 ~~~~ Your program should match this formatting precisely. Note, for example, that there is a blank line between the last input and the beginning of the menu. Note that the line of dashes under "Bobby's Entrees" matches it in length. Also, three columns ares used to list each price. (I.e., if prices are all under $100, still leave space like the $15 and $9 prices above.) You can assume that all prices are whole dollar amounts under $1000. The longest entree item should have two periods between it and its price. The other prices should be aligned to that. There is a built-in function `max` that you can use to help you with this calculation. For the formatting, you'll need to use some combination of the string concatenation, repetition, and length operations, just as in the `marquee.py` exercise. You'll also want to convert integers to strings to get the price spacing right.