Introduction to Python

davidbpython.com




Project Discussion, Session 2



2.1 Notes typing assignment. Please write out this week's transcription notes. The notes are displayed as a .png image named transcription in each week's project files folder.
 
2.2 Reverse Number Guessor. The starter code provided will generate a random integer. Make sure to test the starter code by printing number_to_guess so you can see exactly what it's doing.

The user will be guessing what the random number is, not a fixed number. You should use a while True: loop (NOT A while LOOP WITH A COMPARISON TEST) to allow the user to guess as many times as needed. After the user enters a guess through input() (and the guess is converted to an int so it can be compared to the randomly generated number_to_guess), the program reports (higher, lower, correct) and then the while True: takes program flow back to the top of the loop so the user can guess again. An if/elif/else conditional inside the while True: block can be used to compare the user's guess to number_to_guess to report higher, lower or correct. When the guess is seen to be correct, use break to break out of the while loop. Count the number of tries. Do this with an integer set to 0 before the loop begins, and then increment (add 1 to) the value once inside the loop. Below the loop, you can report the number of tries.

Because this is a tricky assignment, you should not spend too much time fixing the program to get it to work. Use this pseudocode as a guide
generate random number

announce start of game

while True

    ask for guess, 'q' to quit

    if guess == 'q'
        break

    convert input to int

    if int input is greater than random number
        tell user
    elif int input is less than random number
        tell user
    else (guess is correct)
        congratulate user
        break
 
2.3 Text replacement utility. We're going to need two calls to input() to get both the "search text" and the "replacement text". We should be able to use the str.replace() method to do the replacement. As far as the count goes, you'll need to count the number of occurrences of the "search text" in the original text, rather than the number of occurrences of the replacement text in the replaced text -- because what if the replacement text already existed in the original? Your count wouldn't be accurate.

Basic outline:

# take user input:  the text to be replaced
# take user input:  the replacement text

# caling replace() on the text on which to perform the
# replacement, pass the two user input values.  replace()
# returns the replaced text.

# call count() on the original text, passing the "text to be
# replaced" value to see how many occurrences of that value exist
# in the original text.  This could be done before the replacement
# action above, obviously, because we are searching on the original
# text.
 

EXTRA CREDIT / SUPPLEMENTARY

 
2.4 (Extra credit / supplementary) Count from 0 up to 100 by 2's (or 3's, or 4's). Use input() to take user input for a number. The value from input() is a str, so you must convert it to an integer for it to work for us numerically -- we use the int() function to do this. I recommend that this be done before you start calculations. Just convert it once and you won't have to remember to convert it later, or to do it more than once in your program.

Next, the counting loop. The most intuitive approach is to set the counter to 0 before the loop, and then inside the loop print the counter value, and then add the user's integer to it. This way when the while block ends and Python jumps back up to the top of the while loop to test that the counter is less than or equal to 100, it will be testing the incremented value, which it can then print. In fact you can probably just start with a program that counts from 0 and up to 100 by 1's, and then replace the counter = counter + 1 line (whatever your count variable is named) with counter = counter + user_number (whatever you have named your user's variable). Do not use 'break' for this solution. The 'while' test must control. Alternate approach: incremental loop with filter Another approach is to loop through every digit between 0 and (up to) 100 and print only some of them. In other words, we aren't really counting by 2's or 3's, we're simply counting by 1's and printing only every 2nd, 3rd, etc. This solution would involve the modulus operator (%). You can begin building this loop by simply creating a while loop that counts from 1 to 100 and prints out all the numbers in between. That's a good way to begin because it establishes the entirety of what the loop does before the filtering (counting by 2's, etc.) is added. You should test this step before adding in the filtering test. Establish a counting variable (you can call it count) by assigning 0 to count. Then your while test should ask whether count has reached 100 or not; of course this means that we need to add 1 to count inside the loop so that it will eventually reach 100 and then exit. Once you've thoroughly tested your while loop for counting from 1 to 100 and printing each one out, the final step will be to place the print count statement inside an if block, and have the if test check to see if this is one of the values to print. How do we test to see which number to print? We have a step integer that we took from the user. We can see if the number is evenly divisible into the count by using the modulus operator (%). See the slides or pythonreference.com for details on this operator. Here is a list of steps that you can use to construct your program, along with suggested tests to ensure that the program is working as desired. (Note: the suggested tests use print() statements; you can use PyCharm's debugger to verify the same outcome if you prefer.) 1. Take user input and convert to a usable value. What type is the user's input value? What type should it be for use in this code? In this step, please convert the user's input to the proper type. Testing: after converting, test the type of the resulting object and see that it is of the type we'll need for the upcoming functionality. 2. Substitute a test value for the user input so we don't have to retype the value every time we test. At this stage, as long as you have tested thoroughly as instructed, you can declare the first part of the program complete and set it aside for now. To do this, you can temporarily comment out the code you have written so far and replace it with a "hard coded" value that represents the test input. You can comment out a block of code with hash marks, or with the "triple-quoted string". Triple-quotes are used to allow for multi-line strings; they are also used to create a multi-line comment. See the slide for "triple quotes" in the Session 1 deck for an example. Comment out all the code you have written so far, with an understanding that you will be reinstating it later. Below it, put in a single hard-coded integer assignment, such as uinput = 2, but use the variable name you had used for the converted value in the previous step. 3. Put in the print statement announcing how the program will count (as shown in the "Sample program runs" for this problem). Testing: see that the hard-coded announcement you created is printed as part of the announcement. 4. Set up a counting loop that counts every number between 1 and 10. Before trying to solve the entire counting problem, let's take as small a first step as we can. One step you can take is to simply count from 1 to 10, without considering the interval (by 2's, 3's, etc.). This way we can know that we are counting the correct first and last numbers (not starting at 0, for example, or ending at 11). (I'm suggesting counting to 10 because it provides a much more manageable output, after which changing it to go to 100 should be very simple. Set up a while loop to do this, and print out each number as you count. Testing: Run the program and see that you are counting from 1 to 10. 5. Add the interval. Next, modify this loop so that it counts by the interval set in the "hard-coded" value you established in the above step. Testing: is it counting from 1 to 10 by your chosen interval (2's or 3's or 4's, etc.)? 6. Count to 100. Now that all of this is established and tested, you should now be able to count to 100 by the interval as desired, by changing the one "upper limit" value. 7. Restore the input code. Remove the hard-coded "user input" value, uncomment the input() call, and test the program thoroughly by putting in various different values to see that the program counts as specified; make sure to emulate the "Sample program runs" for the assignment to confirm that you're doing everything as specified.

 
2.5 (Extra credit / supplementary) Sum a sequence of integers. This program is very similar to the last program, but instead of counting by a certain interval, is using a 2nd variable to sum up values it encounters as it loops.

Do not use 'break' for this solution. The 'while' test must control. Here are some steps to take, more generally described. As mentioned several times before, please test as you go, verifying that the code you are writing works according to your expectations. The questions we usually ask are: what is the type of this object, and what is the value of this object? Do these two things match what you were expecting your program to do? You can use print() statements to do this (as is generally mentioned below), or you can also take this as a good opportunity to try out the PyCharm debugger to verify each step. Take user input. Now, we have to consider the approach: we want to sum up all values from 0 to a given maximum value. How do we do this? Well, we definitely need to count from 0 to a particular value, so as in the previous step-by-step, you can begin by doing that. Before the loop we'll set an integer count to 0. This while loop will be very similar to the counting loop from the previous assignment; the only difference is that our while test will check to see whether count is less than or equal to the user's input rather than 100. Test this by printing each value of 'count' inside the loop (or use the debugger); run the program several times with different values to see that this works correctly. It's imperative to test this part before moving on because later you'll only see the sum and it will be harder to see what's happening inside the loop. You could even keep this print statement in your program while you're testing so you can continue to have visibility. Later when you've confirmed the program is working properly, you can remove the print statement so the only output is the sum. Next, we need to actually sum up each of the values of count. In other words, it will run like this: before the loop, set a "summing" integer (you can name it my_sum) to 0; also set another integer named count to 0; loop through the values of count, in which your while loop test to see if the count is still less than the user's value; inside the loop, add the value of count to my_sum; increment count; then allow the while loop to loop back. So in the first iteration of the loop my_sum will be 0; in the next it will be 1 (0+1); in the next it will be 3 (1+2); then 6 (3+3), 10 (6+4), etc. After the loop is done, add a print statement that reports (prints) the value of the summing integer. If you're not getting the same result as that shown in the sample program runs, you need to debug. First make sure that you understand the algorithm and how it is supposed to work. In other words, in your head work through the values of count and my_sum and what they are supposed to be in each iteration:

first iteration:  count is 0 and my_sum is 0
second iteration:  count is 1 and my_sum is 1
third iteration:  count is 2 and my_sum is 3
fourth iteration:  count is 3 and my_sum is 6

If this doesn't make sense, you should email me. One of my most important tasks is to reinforce in you the concept that you need to understand everything about how the program is supposed to work and what values the variables should hold at any given time. I realilze that this can be a challenge at first, but this is part of the essence of learning how to code: modeling the program's dynamics in your head. This means that you literally have to keep in mind the value of the two variables and "watch" them change in your head as you "run" the program mentally.

 
2.6 (Extra credit / supplementary) Number Guessor. The key here is keeping track of two numbers: the "maximum value" that the user's number could be (initially, 100) and the "minimum value" that the user's number could be (initially, 1). The guess is made halfway between the two numbers (initially, 50). Once the user identifies that his/her number is higher or lower than the guess, one of the two values can be changed to reflect this information. For example, if the program guesses 50 and the user indicates that his/her number is higher than 50, then the "lowest value" is changed to 50. Now the "halfway" guess will be halfway between 50 and 100.

So after the user hits enter for the first time, the program will enter a while True loop so it can allow the program to guess the number repeatedly. Inside the same loop the program also asks whether or not the number is correct and if not, whether the number is greater or lesser. An input of 'quit' can simply result in a call to exit(). The only other helpful feature is the round() function, which will round float division. This is probably important to do over regular integer division, which also results in an integer but might lead the system to the wrong number.

 
2.7 (Extra credit / supplementary) Find prime numbers in a range of numbers. This program is somewhat more complex than the others -- it requires that we employ a while loop inside a while loop. (A for loop over a range() works as well, but it is recommended to stick with this week's features, particularly while, so they can be thoroughly explored.)

After taking user input for the "max" integer, the "outer" while loop loops over every integer between 2 and the max. This while loop is identifying each "test" number to test for prime-ness. Then inside this while loop, another while loop loops over the values of a second integer between 2 and the "test" number. The idea is that for any given "test" number, we need to check to see whether it is evenly divisible by any integer below it. In other words, for 3 we should check to see whether 2 divides evenly into it (we use the modulus operator for this purpose). For 4 we should check to see whether 2 or 3 divides evenly into it; for 5 we should check 2, 3 and 4. However, if any number divides evenly into the "test" number, we know that the number is not prime and should not be printed. But if we get all the way from 2 to the "test" number without seeing an even division, we know the number is prime and should be printed.

 
2.8 (Extra credit / supplementary) Chicken, Fox and Grain game. Using just the features previously learned, this solution came out to quite a few lines in my solution. (Features discussed in upcoming sessions would make this game much easier to code.)

The game must of course keep track of the position (west bank or east bank) of each of: the chicken, the fox, the grain, and the player. For each of these I chose to use an integer variable with a value of 1 or -1, basically because if I needed to "flip" the position of any of the actors, I needed only to multiply its value by -1. A while True loop is used to allow repetitive "turns" by the player. During a turn, the following happens: 1. we are told the position of each of the actors 2. we are asked what we want to take in the boat for the next trip 3. we see an error if we ask to take an actor that is not currently on the same bank as we are 4. we change the position value of the selected actor, as well as the player's position (since the player goes back and forth with each turn) 5. we check to see whether any of the actors will die as a result of the new positions -- i.e., if the chicken and fox are together in a different position as the player, or the chicken and the grain are together in a different position as the player, the error is printed and the game ends The calculations are of course simple (multiplying the selected actors' values by -1), and it requires only a series of compound tests to detect an error, if any. Finally the program must also be able to detect a successful result, i.e., all four actors' values should indicate their presence on the far bank.

 
[pr]