Day 6: While and String Manipulation

back · home · slides · CMSC 201 (Fall 2024) @ UMBC · while True: print(''.join(['p','y','t','h','o','n']))

CMSC 201: While and Strings

Agenda:

  • HW2/HW3
  • "Fun": ascii art programs
  • Who cares? (AKA: what will we make)
  • For loops review
  • While loops
  • String manipulations
  • Goal: Get familiar with while loops and some string operations, maybe have some fun :)

    My email is: sdonahue@umbc.edu (Shane Donahue), office hours Tu/Th ITE 373 2-3PM

    HW3

    HW3 questions? HW2 questions? HW1 is almost done being graded :)

    Let's look at HW3! (due Sep 27 2024 at 11:59PM)

    First exam is week of October 7th (Oct 9th for M/W and Oct 10th for Tu/Th)! We will be taking it in this room during your section time. TAs will be here to proctor, I unfortunately will not be here :(

    If you have SDS accomodations (e.g., extra time or reduced distractions), please book that room and let them know you plan to take the test there! The room here will be very quiet though, so there won't be many auditory distractions.

    "Fun": ascii art programs

    You may have seen me using programs to make fun animations (matrix animation, fishtank, bonsai tree). These are all called ASCII art! The same ASCII we were using to make a list of letters. Most aren't available on GL :(

  • cmatrix: view the matrix
  • cbonsai: beautfiul trees
  • asciiquarium: world class fishtank
  • nc towel.blinkenlights.nl 23 # --> ???
  • You can make ASCII art! All you need is a text editor and a lot of free time.

    Who cares (about while loops and string manipulations)?

    Let's make a (very quick and very text based) turn based combat! Goal: while either HP is above 0, collect turns. Use a list to store moves. Pokemon, weepingbell vs geodude, https://www.raspberrypi.org/app/uploads/2019/12/pokemon-red.jpg

    Review: Multi-dimensional lists

    You can nest for loops! This is helpful for instantiating multi-dimensional lists.

    Challenge: Make a 2D (two dimensional) array with 8 rows and 8 columns.
    board = []
    for x in range(8):
        new_list = []
        for y in range(8):
            new_list.append("")
    		board.append(new_list)

    We want to write to every element in this 2D list. What's the difference between these programs? Which one works?

    for i in board:
        for j in i:
            j = "X"
            print("The board element is", j)
    for i in range(len(board)):
        for j in range(len(board[i])):
            board[i][j] = "X"
            print('The board at', i, j, 'is', board[i][j])

    The top one is a for-each loop, using a copy of the list elements (pass by value), and the bottom one is a for loop, referencing the original lists. To do that, the bottom one needs the list indicies (indexes).

    While loops

    For loops are cool and all, if you have a list or iterator (like range) to go through. But what if you want to test for a boolean condition?

    While loops are the answer!

    while input() != "y": print("please type y")
    Challenge: Ask the user for a word that has "pizza" in it, until they give one. (While the word does not contain pizza, ask for input.)
    user_input = ""
    while "pizza" not in user_input:
        user_input = input("Pizza please: ")
    
    print("Nice pizza:", user_input)

    Infinite loops

    While loops can run forever :)

    while True: print("forever and ", end="")

    Press CTRL-c to interrupt it!

    This is more dangerous than with for loops, because there is no finite list you can iterate through. (You can do an infinite loop with for lists if your list never ends, but that's less common than messing up a boolean value!)

    Which one exits?

    index = 100
    while index < 1000:
       print("decrementing", index)
       index -= 1
    index = 1500
    while index > 1000:
       print("decrementing", index)
       index -= 1
    Challenge: Calculate user input multipied by index until it is exactly 100.
    index = 1
    while index != 100:
        user_num = float(input("Give number: "))
        index = index * user_num
        # index *= user_num
        print("Index is", index)
    
    print("Done!")

    Loop that never execute

    While loops can run, never :)

    while False: print("never executed")

    This is handy if you want a loop to execute only if some condition was false.

    choice = input("What type of soup: ")
    while "soup" not in choice:
      choice = input("What type of soup?! ")

    Sentinel Values

    "Sentinel" values are values that cause a loop to quit.

    SENTINEL = "DONE"
    new_num = input("Enter an integer, 'DONE' to exit: ")
    integer_list = []
    while new_num != SENTINEL:
       integer_list.append(int(new_num))
       print("Added", new_num)
       new_num = input("Enter an integer: "")
    

    Magic values and constants

    "Magic" values or "magic numbers": random numbers in your code that have no meaning

    days = int(input("How many days since you last washed your car: "))
    next_wash = (days / 44) * 127 # <-- WHAT ARE THESE NUMBERS?
    print("Your next wash will be in", next_wash, "days")

    If you have a number that will never change, you should label it, using all caps so people know it's a CONSTANT.

    AVERAGE_WASH_DAYS = 127
    DAY_COMPRESSION_FACTOR = 44
    days = int(input("How many days since you last washed your car: "))
    next_wash = (days / DAY_COMPRESSION_FACTOR) * AVERAGE_WASH_DAYS # <-- much more clear, at least
    print("Your next wash will be in", next_wash, "days")

    While we call these constants, they are just variables. You can still modify them, but you never should.

    Some Strings

    Semi-preview for next time: strings! Methods that operate on strings:

  • len: get string length
  • strip: remove leading and trailing value, by default, whitespace
  • split: split string into list
  • join: reverse of split: put list into string
  • Challenge: Ask for a comma-delimited list of the places that make up the DMV. Keep asking until they get them all. When they do, print them all back.

    Turn-based battle

    Let's make knock-off pokemon! Two entities, keep going until one has zero HP. Choose moves from list with string input.

    
    # initial variables, names, hp, movelist
    PK_1 = "pikachu"
    PK_1_MOVES = ["thunderbolt", "surf"]
    PK_1_DAMAGES = [9, 8]
    
    PK_2 = "magikarp"
    PK_2_MOVES = ["splash", "celebrate"]
    PK_2_DAMAGES = [4, 1]
    
    pk_1_hp = 16
    pk_2_hp  = 24
    
    MOVE_NOT_FOUND = -1
    
    print("Dododododod... battle commence!", PK_1, "versus", PK_2)
    
    # while loop --> player1 moves, player2 moves, etc
    while pk_2_hp > 0 and pk_1_hp > 0:
        print("======================")
        print(PK_1, "turn!", "hp:", pk_1_hp, "and knows moves", PK_1_MOVES)
        pk_1_choice = input("What move? ")
    
        # Select index and compare value
        choice_index = MOVE_NOT_FOUND
        index = 0 
        for x in PK_1_MOVES:
            if x == pk_1_choice.strip():
                choice_index = index
            index += 1
    
        if choice_index > MOVE_NOT_FOUND:
            print("Wow,", PK_1, "used", PK_1_MOVES[choice_index] + "!")
            pk_2_hp -= PK_1_DAMAGES[choice_index]
        else:
            print(PK_1, "does not know", pk_1_choice)
            
        if pk_2_hp >= 0:
            print(PK_2, "turn!", "hp:", pk_2_hp, " and knows moves", PK_2_MOVES)
            pk_2_choice = input("What move? ")
            choice_index = MOVE_NOT_FOUND
            index = 0 
            for x in PK_2_MOVES:
                if x == pk_2_choice.strip():
                    choice_index = index
                index += 1
    
            if choice_index > MOVE_NOT_FOUND:
                print("Wow,", PK_2, "used", PK_2_MOVES[choice_index] + "!")
                pk_1_hp -= PK_2_DAMAGES[choice_index]
            else:
                print(PK_2, "does not know", pk_2_choice)
                
    if pk_1_hp <= 0:
        print(PK_1, "fainted!")
    else:
        print(PK_2, "fainted!")