Section #4 Solutions

February 7th, 2021


Written by Juliette Woodrow, Brahm Capoor, Nick Parlante, and John Dalloul

String Parsing and Lists

                    
def exclaim_words(s):
    search = 0
    words = []
    while True:
        exclaim = s.find('!', search)
        if exclaim == -1:
            break
        
        # Your code here
        pass
        # Move begin left over alpha chars
        begin = exclaim - 1
        while begin >= 0 and s[begin].isalpha():
            begin -= 1
        
        # In this case, begin is on the first *non* alpha
        word = s[begin + 1:exclaim + 1]
        if len(word) >= 2:  # 1 or more alpha + the !
            words.append(word)

        # Set up next loop
        search = exclaim + 1
    return words


def parse_unique_categories(s):
    categories = []
    # need to keep a running start index so we don't only find the first category
    start_index = 0
    # keep looking for more categories as long as we haven't reached the end of the string
    # and there are more categories to be found
    while start_index < len(s) and s.find("[", start_index) != -1:
        # parse out the next category
        curr_categ_start = s.find("[", start_index)
        curr_categ_end = s.find("]", start_index)
        curr_categ = s[curr_categ_start + 1:curr_categ_end]
        # add it to our list only if it's unique
        if curr_categ not in categories:
            categories.append(curr_categ)
        # update the index at which we start our search for another category
        start_index = curr_categ_end + 1
    
    return categories


def parse_words(s):
    # create empty list
    email_components = []
    # find indices for separating characters
    first_dot_index = s.find(".")
    second_dot_index = s.find(".", first_dot_index+1)
    at_symbol_index = s.find("@")
    # append components to list
    email_components.append(s[:dot_index])
    email_components.append(s[dot_index + 1:at_symbol_index])
    email_components.append(s[at_symbol_index + 1:second_dot_index])
​
    return email_components


def parse_out_hashtags(s):
    start_search_indx = 0
    hashtag_lst = []
    while True:
      octothorpe_loc = s.find('#', start_search_indx)
      
      #out of hashtags, so stop searching 
      if octothorpe_loc == -1:
        break

      end = octothorpe_loc + 1

      while end < len(s) and s[end].isalnum():
        end += 1

      curr_hashtag = s[octothorpe_loc + 1:end]

      #only add a hashtag that isn't an empty string
      if curr_hashtag != '':
        hashtag_lst.append(curr_hashtag)

      start_search_indx = end  # the next character might be a hashtag
  
    return hashtag_lst


def parse_phone_number(s):
    """
    This function uses indexing to parse a string representing a 10 digit phone number into a list of strings
    where the first string is the area code of the given phone number and the second string is the rest of 
    the phone number with the dash characters removed. 
    """
    area_code = s[:3]
    rest_of_num_with_dash = s[4:]
    dash_loc = rest_of_num_with_dash.find('-')
    rest_of_num_no_dash = rest_of_num_with_dash[0:dash_loc] + rest_of_num_with_dash[dash_loc+1:]
    output_lst = [area_code, rest_of_num_no_dash]
    return output_lst


def parse_phone_number(s):
    """
    This function uses a while loop accompanied with str.find() to parse a phone number into a list of strings
    where the first string is the area code of the given phone number and the second string is the rest of 
    the phone number with the dash characters removed. This function will work for all phone numbers, 
    not just 10 digit ones. 
    """
    output_lst = []
    num_split_by_dash = []
    start_search_indx = 0
    while True:
      dash_location = s.find('-', start_search_indx)
      if dash_location == -1:
        break
      else:
        num_split_by_dash.append(s[start_search_indx:dash_location])
        start_search_indx = dash_location + 1
 
    num_split_by_dash.append(s[start_search_indx:])

    area_code = num_split_by_dash[0]
    
    rest_of_num_no_dash = ''
    for part in num_split_by_dash[1:]:
      rest_of_num_no_dash += part
      
    output_lst.append(area_code)
    output_lst.append(rest_of_num_no_dash)

    return output_lst

                    
                

Drawing

                

# given constants
SQUARE_SIDE_LENGTH_RATIO = 0.27
​
# added constants for stylistic reasons
NUM_STRIPES = 9


def draw_stanford_flag(canvas, left_x, top_y, width, height):
    """
    This function draws the outline of the new Stanford flag at the given location
    with the given width and height. The parameters are:
        - canvas: the canvas on which to draw the flag
        - left_x: the x coordinate for the upper left corner of the flag
        - top_y: the y coordinate for the upper left corner of the flag
        - width: the total width of the flag
        - height: the total height of the flag
    """
    stripe_thickness = height / NUM_STRIPES
    # draw the stripes - only need to draw the 5 red stripes
    start_x = left_x
    for i in range(NUM_STRIPES // 2 + 1):
        # calculate the y coordinate for the upper left corner of the current stripe
        curr_y = top_y + i * (stripe_thickness * 2)
        canvas.fill_rect(start_x, curr_y, width, stripe_thickness, color = "red")
​
    # draw the green square
    square_side_length = SQUARE_SIDE_LENGTH_RATIO * width 
    square_left = left_x + width // 2 - square_side_length // 2 # x coord for upper left corner
    square_top = top_y + height // 2 - square_side_length // 2 # y coord for upper left corner
    canvas.fill_rect(square_left, square_top, square_side_length, square_side_length, color = "green")


def draw_flags(canvas, width, height):
    """
    This function draws three identical flags on the given canvas, one in the bottom
    left corner, one in the top center, and one in the bottom right corner. The parameters
    are:
        - canvas: the canvas on which to draw the flags
        - width: the total width of the canvas
        - height: the total height of the canvas
    """
    # calculate reference points for flags
    middle = height // 2
    third = width // 3
    # draw flags
    draw_stanford_flag(canvas, 0, middle, third, height - middle)
    draw_stanford_flag(canvas, third, 0, third, middle)
    draw_stanford_flag(canvas, third * 2, middle, third, height - middle)
                
            

Main

            
"""
calculator.py
-------------
Implements the calculator program, as specified in the
section 4 handout.
"""
import sys 

def exp(base, power):
    total = 1
    for i in range(power):
        total *= base
    return total

def square(base):
    return exp(base, 2)

def add(nums):
    total = 0
    for i in range(len(nums)):
        total += int(nums[i])
    return total

def main():
    args = sys.argv[1:]

    operation = args[0]

    if operation == "-exp":
        base = int(args[1]) # convert the argument to an int
        power = int(args[2])
        result = exp(base, power)
        print(result)

    if operation == "-square":
        base = int(args[1])
        result = square(base)
        print(result)

    if operation == "-add":
        nums = args[1:]
        result = add(nums)
        print(results)

if __name__ == "__main__":
    main()