Skip to content

Oct 07: Solving Problems with Loops

Learning Objectives

After today's class, you should be able to:

  • Use a loop to find and count words in a dictionary.
  • Write a loop that computes the min, max, and sum.
  • Solve problems that compare previous/next values.
  • Explain how to use the from keyword in an import statement.
  • Describe how functions in a test module use assert statements.

Reminders

  • Due tomorrow
  • Quiz 3 on Thursday
    • Based on HW 5 and HW 6
    • No for – only while
    • Review questions from practice quiz and rework homeworks 5 and 6.
  • Chapter 8 reading is posted
  • Start Project 1, it is due Oct 21

New (second) Textbook!

From the Enroll in a Course page on Runestone:

  • Please leave your Username, First Name, Last Name, and Email unchanged.
  • Use jmucs149-2-fa25-simmonsj (note the 2) for the course name. You now have two free Python books! This week's reading is in the new book.

for loops

  • variable name should align with what is being iterated, don't always use i
Code Meaning
for value in my_list: For each value in a list
for index in range(len(my_list)): For each index in a list
for index, value in enumerate(my_list): For each index and value
for key in my_dict: For each key in a dict
for key, value in my_dict.items(): For each key and value

Exercise

Given a string, print each uppercase letter along with its index. Ex: print_upper("James Madison Computer Science") should print:

J at 0
M at 6
C at 14
S at 23

Exercise

Given a sentence, count how many times each word occurs. Use a dictionary to keep track of the count of each word. Ex: count_words("mat the cat sat on the mat") should return:

{'mat': 2, 'the': 2, 'cat': 1, 'sat': 1, 'on': 1}

Min, Max, Sum

  • the built-in functions min(), max(), sum(). The implementation of these require a loop. The code for these may look something like this:
    def my_min(sequence):
        result = sequence[0]
        for value in sequence:
            if value < result:  # found new minimum
              result = value
     return result

    def my_max(sequence):
        result = sequence[0]
        for value in sequence:
            if value > result:  # found new maximum
                result = value
        return result

    def my_sum(sequence):
        result = 0
        for value in sequence:
            result += value     # add running total
        return result


    if __name__ == "__main__":
        print("min:", my_min([13, -5, 100, 0, 77]))
        print("max:", my_max([13, -5, 100, 0, 77]))
        print("sum:", my_sum([13, -5, 100, 0, 77]))

Question

What happens with this line of code: sum(grades)/max (grades)? How many loops are executed?

Exercise

Find the index of the maximum value in a list. Ex. index_max([13, -5, 100, 0, 77]) returns 2, because the maximum value 100 is at index 2.

Exercise

Count how many characters in a string are digits. Ex. count_digits("Today is 10/03/2023!") returns 8, because 8 of the characters are digits.

Looking Ahead

  • Sometimes a loop needs to look at index [i + 1].
  • In that case, the range should end at len(s) - 1.
def is_sorted(seq):
    for i in range(len(seq) - 1):
        if seq[i] > seq[i + 1]:
            return False
    return True


if __name__ == "__main__":
    print("yes sorted:", is_sorted([1, 5, 10, 13, 16]))
    print("not sorted:", is_sorted([1, 5, 13, 16, 10]))

Question

what is the return of range(len(seq) -1) if seq has 10 elements?

Exercise

Write a function, two_in_row, that returns True if two consecutive values are equal.

Ex: two_in_row(["Pizza", "Soda", "Soda", "Candy", "Salad"]) returns True because of two "Soda" in a row.

Exercise

Write a function, three_in_row, that returns True if three consecutive values are equal.

Ex: three_in_row(["Apple", "Banana", "Cherry", "Cherry", "Cherry"]) returns True because of three "Cherry" in a row.

Extra Practice

CodingBat.com is a free site of live problems to build skill in Java and/or Python. CodingBat was created by Nick Parlante, who is Computer Science lecturer at Stanford.

Note: Do not use the built-in min(), max(), or sum() functions for any of these problems.

List-2 Problems

  • Easier: count_evens, has22
  • Medium: big_diff, sum13
  • Harder: centered_average, sum67

String-2 Problems

  • Easier: double_char, count_hi
  • Medium: count_code, cat_dog
  • Harder: xyz_there, end_other

Week 8 new material

Difference between a script and a module

  • Importing a module from the same folder
  • Optional: from module import function
  • The __pycache__ folder (auto generated)

Example tests for HW6.1

An assert statement is used to see if each function call returns the expected tuple.

test_division.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from division import divide

def test_divide_0_by_10():
    assert divide(0, 10) == (0, 0)

def test_divide_134_by_7():
    assert divide(134, 7) == (19, 1)

def test_divide_56_by_57():
    assert divide(56, 57) == (0, 56)

def test_divide_56_by_16():
    assert divide(56, 16) == (3, 8)

Example tests for HW6.5 – not assigned this year

The capsys argument (provided by pytest) automatically captures system output and error messages. Notice in the assert statement how listing multiple string literals automatically combines them into a single string.

test_even_more.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from even_more_stats import print_stats

def test_one_player(capsys):
    stats = [('Jefferson', 706, 88, 57)]
    print_stats(stats)
    out, err = capsys.readouterr()
    assert err == ""
    assert out == (
        "Jefferson scored 706 points, grabbed 88 rebounds, and made 57 assists.\n"
        "Total Points:   706\n"
        "Total Rebounds: 88\n"
        "Total Assists:  57\n"
    )

def test_two_players(capsys):
    stats = [('Hazell', 615, 62, 62), ('Tucker', 551, 137, 17)]
    print_stats(stats)
    out, err = capsys.readouterr()
    assert err == ""
    assert out == (
        "Hazell scored 615 points, grabbed 62 rebounds, and made 62 assists.\n"
        "Tucker scored 551 points, grabbed 137 rebounds, and made 17 assists.\n"
        "Total Points:   1166\n"
        "Total Rebounds: 199\n"
        "Total Assists:  79\n"
    )

Extra Examples for outside of class

More to keep learning

  • trace by hand
  • what is each code snippet doing?
  • run and test in thonny

1

word = "onomatopoeia"
locs = []
for i in range(len(word)):
    if word[i] in ('a', 'e', 'i', 'o', 'u'):
        locs.append(i)
print("Locations:", locs)

2

count = 0
prev = 0
words = ["Book", "Car", "City", "Dog", "Enough", "Friend", "House"]
for w in words:
    if len(w) < prev:
        count += 1
    prev = len(w)
print("Count is", count)

3

name = "James Madison University"
words = name.split()
acronym = ""
for word in words:
    letter = word[0]
    print(letter, "is for", word)
    acronym += letter
print(acronym)

4

index = None
word = "Mississippi"
for i in range(len(word)-1):
    if word[i] == word[i+1]:
        index = i
print("Index is", index)

Even more to practice

Short words

Write a function named get_short(words) that takes a list of words and returns the words that have at most 5 letters. Do not change the list you are given. Instead, follow these steps:

  1. Create an empty list.
  2. Write a for loop that adds one word at a time to the list.
  3. Return the resulting list. (At the end, not in the loop!)

Repeat the exercise using set and dict as the return type. For dict, use the word for the key and the length for the value.

Hotel Ratings

Write a function named five_star(hotels) that takes a dictionary of hotel names and ratings. Return a list of hotels that have a rating of 4.5 or higher. Ex: Given {"Ritz": 5.0, "Marriott": 4.5, "Madison": 4.2}, return ["Ritz", "Marriott"].

Repeat the exercise using a list of tuples as the input. Ex: [("Ritz", 5.0), ("Marriott", 4.5), ("Madison", 4.2)].