COMP1701-004

fall 2023

lec-13

What's Next?

about A3

heads-ups

  1. respect the ladder
  2. you must use your MRU username
  3. do NOT change the headings of any functions present
  4. follow the instructions in the docstrings present
  5. watch those decision boo-boos (lec-10) in some code
  6. watch those magic numbers
  7. watch those multiple returns (even though me personally likey)
  8. let's go through the Grading Section now

RECALL

# Complete wall_dimensions_from_user
# Complete paint_available_from_user
# Make a bool-returning function, enough_paint

def main() -> None:
  wall_width = wall_dimension_from_user("width")
  wall_height = wall_dimension_from_user("height")
  wall_area = wall_width * wall_height
  
  paint_avail = paint_available_from_user()
  
  # Report whether enough paint is available to 
  # complete painting the given wall, using
  # enough_paint function.
  # 
  # Assume 1L of paint will cover 6 square metres
  # of wall.

Complete this code

let's talk about these  things today:

 looping

 the while loop

input validation

 tracing while loops

What can a CPU do again?

  • read from an input device

  • write to an output device

  • read a value from storage

  • write a value to storage

  • "do math"

  • branch

  • loop (repeated branching)

That's the last one!

  • read from an input device

  • write to an output device

  • read a value from storage

  • write a value to storage

  • "do math"

  • branch

  • loop (repeated branching)

looping

Naturally, we should celebrate this momentous occasion...

...with a song.

looping

99 bottles of age-appropriate beverages on the wall,
99 bottles of age-appropriate beverages,
take one down, pass it around,
98 bottles of age-appropriate beverages on the wall.

98 bottles of age-appropriate beverages on the wall,

98 bottles of age-appropriate beverages,
take one down, pass it around,
97 bottles of age-appropriate beverages on the wall.

97 bottles of age-appropriate beverages on the wall,

97 bottles of age-appropriate beverages,
take one down, pass it around,
96 bottles of age-appropriate beverages on the wall.

...

The Song

I just had to change this...
it sounded so wrong otherwise!

looping

let number_of_bottles = 99

while number_of_bottles is greater than 2
   print "[number_of_bottles] bottles of age-appropriate beverages on the wall,"
   print "[number_of_bottles] bottles of age-appropriate beverages,"
   print "take one down, pass it around,"
   let number_of_bottles = number_of_bottles - 1
   print "[number_of_bottles] bottles of age-appropriate beverages on the wall,"

print "2 bottles of age-appropriate beverages on the wall,"
print "2 bottles of age-appropriate beverages,"
print "take one down, pass it around,"
print "1 bottle of age-appropriate beverages on the wall,"

print "1 bottle of age-appropriate beverages on the wall,"
print "1 bottle of age-appropriate beverages,"
print "Nah nah nah nah nah nah nah nah nah"...

The Psong as Pseudocode

the while loop

the while loop

Our first while loop

def sing_that_song():

    number_of_bottles = 99

    while number_of_bottles > 2:
        print(f"{number_of_bottles} bottles of age-appropriate beverages on the wall,")
        print(f"{number_of_bottles} bottles of age-appropriate beverages,")
        print("take one down, pass it around,")
        
        number_of_bottles = number_of_bottles - 1

        print(f"{number_of_bottles} bottles of age-appropriate beverages on the wall,")
        print()
        

    print("2 bottles of age-appropriate beverages on the wall,")
    print("2 bottles of age-appropriate beverages,")
    print("take one down, pass it around,")
    print("1 bottle of age-appropriate beverages on the wall,")
    print()

    print("1 bottle of age-appropriate beverages on the wall,")
    print("1 bottle of age-appropriate beverages,")
    print("Nah nah nah nah nah nah nah nah nah...")


sing_that_song()

I am giddy with excitement and age-appropriate beverages!

🙋🏻‍♂️❓🙋🏻‍♀️Why no loop on the last 2 stanzas?

number_of_bottles = 99

while number_of_bottles > 2:
  
  print(f"{number_of_bottles} bottles ...")
  print(f"{number_of_bottles} bottles ...")
  print("take one down, pass it around,")
  number_of_bottles = number_of_bottles - 1
  print(f"{number_of_bottles} bottles ...")
  print()

You need a while to have a while loop!

You need a condition to determine what keeps the loop going.

The condition uses a variable - the LCV (loop control variable).

The LCV should be given a useful initial value.

The LCV should be changed inside the loop.

You need one or more statements to run while your loop is going. (the loop body)

the while loop

Every while loop has the same basic parts

They all are important!

number_of_bottles = 99

while number_of_bottles > 2:
  
  print(f"{number_of_bottles} bottles ...")
  print(f"{number_of_bottles} bottles ...")
  print("take one down, pass it around,")
  number_of_bottles = number_of_bottles - 1
  print(f"{number_of_bottles} bottles ...")
  print()

For some reason, it can be easier to think "When should I NOT loop?" and then FLIP that condition.

For this code, we DON'T want to loop when we have 1 or 2 bottles - that's to say, when number_of_bottles <= 2. So flip that.

input validation

while loops work nicely with pesky unpredictable input

TASK

Make a function that asks how many pets you have.
If the number entered is less than 0, re-prompt and ask again;
otherwise, return the number.
Assume (for now) an integer is entered.

input validation

TASK

Make a function that asks how many pets you have. If the number entered is less than 0, re-prompt and ask again; otherwise, return the number.
Assume (for now) an integer is entered.

Create an expressive name for our function. Any suggestions?

def num_pets_from_user() -> int:
    return -1

Sure, this isn't necessary -
but you have to admit, it's kinda helpful...

I tend to put the return in right away, just so I don't forget. And I choose an invalid number, because it's useful for automated testing - but you'll have to just take my word for that.

input validation

I was super close to calling this valid_num_pets_from_user...but that might be a bit long.
Hard to tell!

🙋🏻‍♂️❓🙋🏻‍♀️What category of function is this? What's the other?

TASK

Make a function that asks how many pets you have. If the number entered is less than 0, re-prompt and ask again; otherwise, return the number.
Assume (for now) an integer is entered.

Attempt to get what we need.

def num_pets_from_user() -> int:
    num_pets = int(input("How many pets? "))
    
    return -1

Remember, we want to eventually return an int!

Naming things expressively becomes something you can do on autopilot here.

Don't forget spaces after prompts!
Attention to detail is a habit we try to cultivate.

This initial asking of input from the user is called a priming read.
Yes, you should memorize that term.

input validation

🙋🏻‍♂️❓🙋🏻‍♀️What do we call this process of turning something of one type into another?

TASK

Make a function that asks how many pets you have. If the number entered is less than 0, re-prompt and ask again; otherwise, return the number.
Assume (for now) an integer is entered.

If the user is being difficult, we need to pester them until they stop.

def num_pets_from_user() -> int:
    num_pets = int(input("How many pets? "))

    while num_pets < 0:
        print("Num of pets must be >=0.")
        num_pets = int(input("How many pets? "))
    
    return -1

We can print a "naughty-naughty" warning if we want to. It's usually friendlier to do so than not.

See if there is invalid input - if so, we've got work to do!

Remember to get their new response! And note how this line is IDENTICAL to our priming read...

input validation

Remember:
It can be easier to ask "when should I NOT loop?" and then flip it.

TASK

Make a function that asks how many pets you have. If the number entered is less than 0, re-prompt and ask again; otherwise, return the number.
Assume (for now) an integer is entered.

Finally, don't forget to return the validated input!

def num_pets_from_user() -> int:
    num_pets = int(input("How many pets? "))

    while num_pets < 0:
        print("Num of pets must be >=0.")
        num_pets = int(input("How many pets? "))
    
    return num_pets

input validation

TASK

Make a function that asks how many pets you have. If the number entered is less than 0, re-prompt and ask again; otherwise, return the number.
Assume (for now) an integer is entered.

Note that all our important "while parts" are present here!

def num_pets_from_user() -> int:
    num_pets = int(input("How many pets? "))

    while num_pets < 0:
        print("Num of pets must be >=0.")
        num_pets = int(input("How many pets? "))
    
    return num_pets

input validation

You need a while to have a while loop!

You need a condition to determine what keeps the loop going.

The condition uses a variable - the LCV (loop control variable).

The LCV should be given a useful initial value.

The LCV should be changed inside the loop.

You need one or more statements to run while your loop is going. (the loop body)

TASK

Change the function so that now we DON'T assume the user enters an integer - now we want to see if it's an integer AS WELL AS >= 0

 

Hint: the isdigit() method can be used with strings. It returns True iff every character in the string is a digit. For example:

"12".isdigit() is True
"hi!".isdigit() is False
"5.12".isdigit() is False
"-2".isdigit() is False
def num_pets_from_user() -> int:
    num_pets = int(input("How many pets? "))

    while num_pets < 0:
        print("Num of pets must be >=0.")
        num_pets = int(input("How many pets? "))
    
    return num_pets

tracing while loops

tracing while loops

HONOURS_CUTOFF = 3.6
PASS_CUTOFF = 2.0


def display_grade_stats(num_students: int) -> None:

    student_count = 0
    num_honours = 0
    num_passed = 0
    num_failed = 0

    while student_count < num_students:
        gpa = float(input(f"Student {student_count + 1} GPA: "))

        if gpa >= HONOURS_CUTOFF:
            num_honours += 1
        elif gpa >= PASS_CUTOFF:
            num_passed += 1
        else:
            num_failed += 1

        student_count += 1

    print(f'''h: {num_honours} p: {num_passed} f: {num_failed}''')


# Call for 3 students, entering 3, 4, 1
display_grade_stats(3)

New thing
augmented assignment operator

Trace this!

🙋🏻‍♂️❓🙋🏻‍♀️What dangerous thing is this function doing?

🙋🏻‍♂️❓🙋🏻‍♀️There's a subtle logic error here. See it?

Remember:
It can be easier to ask "when should I NOT loop?" and then flip it.

lec-13

By Jordan Pratt

lec-13

looping | the while loop | input validation | tracing while loops

  • 280