Learning to Code: Harvard CS50 Week 3 Loops

Hey everybody! I have to say, this week’s course was way more dense than what we’ve done previously. In the lecture, we covered all of the following functions: whileforlistrangecontinuebreaklistlendict. These functions are the building blocks for one of the most important concepts in any computer science language: loops. Loops are super useful because they allow a task to be completed many times while only writing it out once. They’re not completely necessary, but they really are when you think about CS from an efficiency perspective. Who wants to write out print() hundreds of times? I sure don’t.

Now that we’ve discussed the importance of loops, let’s examine the different functions we covered in the lesson more in-depth. First, let’s start with while loops.

i = 3
while i != 0:
    print("meow")
    i = i - 1

Here, we start with a variable, i. We will continue to print the word “meow” until i equals zero. However, every time we run the while loop, i will decrease by 1. This last step is super important because if you don’t change the value of i, the loops will run forever and crash your computer. If this happens, hit ctrl-c for cancel.

while True:
    n = int(input("What's n? "))
    if n > 0:
        break

for _ in range(n):
    print("Meow")

We can also use boolean values for while loops. These loops will run until they meet a condition that “breaks” them. We could also say “continue” which means continue to run the loop. In this code, the computer will ask the user for “n” until the user gives them a positive value. Now, we introduce a different type of loop, “for”. A for loop will run the loop for every value in a given list. A list could be as simple as [0, 1, 2], in which case the loop would run 3 times. Here, we use a range function, which counts the amount of values in a list. So if we say the range is n, it will print(“Meow”) n times.

students = ["Hermione", "Harry", "Ron"]

for i in range(len(students)):
    print(students[i])

Here, we define a list called students. Then in the for loop we introduce variable i in a range. Now, range is meant to function with integers, so string values aren’t going to work. This is where the len (length I think) function comes in. len will output the number of string values in a list, converting the list to integers. Now we print students[i]. The brackets at the end are an easy way to denote with students value we want. In this case, “Hermione” would be students[0], “Harry” would be students[1], and “Ron” would be students[2].

students = {
    "Hermione": "Gryffindor",
    "Harry": "Gryffindor",
    "Ron": "Gryffindor",
    "Draco": "Slytherin",
}

for student in students:
    print(student, students[student])

Now, we’re getting complicated. Here, we are using a direct (dictionary) function. A direct function is an easy way to group values together in a list. We are building a data set. Just like in a language dictionary, a word is tied to its definition. Once we have a dict, we can use a for loop to call the initial value and then the value it’s tied to. Think of student (not to be confused with students) as the variable i we have used previously.

students = [
    {"name": "Hermione", "house": "Gryffindor", "patronus": "Otter"},
    {"name": "Harry", "house": "Gryffindor", "patronus": "Stag"},
    {"name": "Ron", "house": "Gryffindor", "patronus": "Jack Russel Terrier"},
    {"name": "Draco", "house": "Slytherin", "patronus": None},
]

for student in students:
    print(student["name"], student["house"], student["patronus"], sep=", ")

Even more complicated! Here we are making a list of dict’s. Notice how we have solid brackets surrounding different curly bracket values. Each curly bracket is its own dict. It assigns a value to “name,” “house,” and “patronus.” It’s just an even larger data set. Then we use a for loop to print a list of each respective name, house, and patronus in the terminal.

def main():
    print_square(int(input("What size? ")))


def print_square(size):
    #for each row in square
    for i in range(size):
        #for each brick in row
        for j in range(size):
            #Print brick
            print("#", end="")
        print()


main()

We are writing a program to print a square of # in the terminal. We nest for loops to do it. Remember, a # is a comment, but a “#” is a literal hash. It’s easier to understand if we think about it reading top down, right to left. We create a loop to create the horizontal rows of x amount of hashes. Then, we nest it inside another for loop, which creates a new line for each row.

Problem 1: camelCase

I will admit this problem was pretty difficult for me. I spent a long time searching the Python documentation for a function that could detect if a single character was capitalized and found nothing. I was stuck so I turned to google. There I found a very helpful answer using the char (character function). Even though I did cheat, I feel it really wasn’t cheating because I learned something I otherwise wouldn’t have.

Basically, we start with the variable “snakecase” being equal to nothing. Then we scrape every character in the user input to check if it’s uppercase. If it is, we add an underscore, make it lowercase, and then add it to the snakecase variable. If it is already lowercase, we do nothing and add it to the snakecase variable. This way, we construct the snake case variable character by character.

user_input = input("CamelCase: ")
snakecase = ""

for char in user_input:
    if char.isupper():
        snakecase += "_" + char.lower()
    else:
        snakecase += char
print("snake_case: ", snakecase)

Problem 2: Coke Machine

This one was challenging, but I was proud because I did it without cheating. Basically, I started by defining a function (ask_balance()) that would return the remaining price of the Coke if the user inputted a viable integer amount. Otherwise, the loop would ask the user to input another coin. Then, I ran that function after setting price = 50. If the price was still greater than zero, the loop would continue to run until it wasn’t. Once the price was less than or equal to zero, I used the absolute value function to print the change owed.

price = 50

def ask_balance(cost):
    while True:
        user_input = int(input("Insert Coin:"))
        match user_input:
            case 25 | 10 | 5:
                return cost - user_input
                break
            case _:
                return cost
                break
while True:
    if price > 0:
        price = ask_balance(price)
        if price > 0:
            print("Amount Due:", price)
        continue
    elif price <= 0:
        print("Change Owed:", abs(price))
        break

Problem 3: Just setting up my twttr

This problem was easy, mostly because the concept was exactly the same as the first problem. I won’t go into much detail because I’ve already reviewed the concept.

user_input = input("Input:")
output = ""

for char in user_input:
    match char:
        case "A" | "a" | "E" | "e" | "I" | "i" | "O" | "o" | "U" | "u":
            output = output
        case _:
            output += char

print(output)

Problem 4: Vanity Plates

Im not gonna lie to you guys, I cheated hard on this one. The lecture didn’t cover almost all of the syntax required for this problem. First I looked up the answer on github, then I went to youtube where the video was wrong, on my second youtube video I had the code but I didn’t understand it, so finally I went to chatgpt to explain it. All in all, I think the only thing that really matters is what I learned, which was a lot.

So basically we have to define is_valid() using the required constraints. We can use pretty simple str functions for most of it. .isalpha() will tell if the characters are letters, which is useful for the first requirement. I had to learn the s[0:2] which only affects the first 2 characters in the string. Then I can use len() to make sure the length fits the constraints. Then I can use .isalnum to ensure all the characters are letters, numbers, and no other symbols.

The hard part was the function no_middle_num(). This is the part I had to look up. We will use a for loop to test for every character in the string. If the character is a digit, we index it. Indexing was completely new to me. Basically it identifies the position in the string of a value. Then we will make a substring of all the values after the initial digit to the end of the string. The s[index:] was very confusing for me. If those are all digits and the initial digit is not a zero, it outputs True. It also outputs True if there are no digits.

def main():
    plate = input("Plate: ")
    if is_valid(plate):
        print("Valid")
    else:
        print("Invalid")


def is_valid(s):
    if s[0:2].isalpha() and 2<=len(s)<=6 and s.isalnum and no_middle_num(s):
        return True

def no_middle_num(s):
    for char in s:
        if char.isdigit():
            index = s.index(char)
            if s[index:].isdigit() and int(char) != 0:
                return True
            else:
                return False
    return True



main()

Problem 5: Nutrition Facts

This problem was a simple data recall from a dictionary I set up. I created a dict called food_table associating 20 fruits with their corresponding calories per serving. Then I asked the user for a fruit. If the fruit was in food_table, the program would print the calories.

food_table = {
    "apple": "130",
    "avocado": "50",
    "banana": "110",
    "cantaloupe": "50",
    "grapefruit": "60",
    "grapes": "90",
    "honeydew Melon": "50",
    "kiwifruit": "90",
    "lemon": "15",
    "lime": "20",
    "nectarine": "60",
    "orange": "80",
    "peach": "60",
    "pear": "100",
    "pineapple": "50",
    "plums": "70",
    "strawberries": "50",
    "sweet cherries": "100",
    "tangerine": "50",
    "watermelon": "80",

}

user_input = input("Item:").strip().lower()
if user_input in food_table:
    print("Calories:", food_table[user_input])

Thats it for week 2 of Harvard’s CS50. I enjoyed this week because I felt challenged. The problem set was fun, though difficult because most of the material wasn’t in the lecture. Looking forward to week 3.