Quiz Review 3 Solutions

March 9th, 2021


Written by Juliette Woodrow, Brahm Capoor, and Nick Parlante

One Liners

  • Given list of non-empty strs, write a map/lambda to form a list of the strings in upper case.
                    
        >>> strs = ['Rhyme', 'Donut', '3xx', 'Orange']
    >>> list(map(lambda s: s.upper(), strs))
                    
                  
  • Given list of (x, y) points, write a sorted/lambda expression to order these points in decreasing order by the sum of the x+y of each point.
                    
        >>> points = [(10, 0), (1, 3), (3, 2), (5, 4)]
    >>> sorted(points, key=lambda pt: pt[0] + pt[1], reverse=True)
                    
                  

Dictionaries


Emails

                
def parse_hosts(addrs):
    """
    >>> parse_hosts(['a@x', 'b@x', 'a@x'])
    {'x': ['a', 'b']}
    >>> parse_hosts(['a@x', 'b@x', 'a@y'])
    {'x': ['a', 'b'], 'y': ['a']}
    >>> parse_hosts(['a@x', 'bob@x', 'c@z'])
    {'x': ['a', 'bob'], 'z': ['c']}
    """
    hosts = {}
    for addr in addrs:
        at = addr.find('@')
        user = addr[:at]
        host = addr[at + 1:]
        if host not in hosts:
            hosts[host] = []
        users = hosts[host]    # style: decomp by var
        if user not in users:  # no duplicates
            users.append(user)
    return hosts
                
            

Sent Messages

                
def parse_sends(filename):
    with open(filename, 'r') as f:
        sends = {}
        for line in f:
            line = line.strip()  # \n handling, not marking off for this
            parts = line.split(',')
            src = parts[0]
            if src not in sends:
                sends[src] = {}
            nested = sends[src]  # decomp by var
            for dst in parts[1:]:
                if dst not in nested:
                    nested[dst] = 0
                nested[dst] += 1
    return sends
                
            

Common Senders

                
def commons(sends, srca, srcb):
    countsa = sends[srca]  # Given that srca/b are in sends
    countsb = sends[srcb]  # so don't need "in" check first.
    result = []
    for dest in countsa.keys():
        # is it in b too? "in" handy here
        if dest in countsb:  
            result.append(dest)
    return result
                
            

Make County

                
def make_county(words):
    """
    Given a list of non-empty words, produce 'county' dict
    where each first-char-of-word seen is a key, and its value
    is a count dict of words starting with that char.
    So ['aaa', 'abb', 'aaa'] yields {'a': {'aaa': 2, 'abb': 1}}
    """
    county = {}
    for word in words:
        ch = word[0]
        if ch not in county:
            county[ch] = {}
        inner = county[ch]
        if not word in inner:
            inner[word] = 0
        inner[word] += 1
    return county
                
            

Recipes

                
def is_sub_list(curr_ingredients, recipe_ingredients):
    for ingredient in recipe_ingredients:
        if ingredient not in curr_ingredients:
            return False
    return True

def find_recipes(curr_ingredients, recipe_book):
    possible_recipes = []
    for recipe in recipe_book:
        recipe_ingredients = recipe_book[recipe]
        if is_sub_list(curr_ingredients, recipe_ingredients):
            possible_recipes.append(recipe)

    return possible_recipes
                
            

Building a Glossary

                
def make_glossary(filename):
    glossary = {}

    with open(filename, 'r') as f:
        line_num = 0
        for line in f:
            line = line.strip()
            for word in line.split():
                if word not in glossary:
                    glossary[word] = []
                glossary[word].append((line_num, line))
            line_num += 1

    return glossary
                
            

Finding Grandparents

                
SAMPLE_INPUT = {
    'Khaled': ['Chibundu', 'Jesmyn'],
    'Daniel': ['Khaled', 'Eve'],
    'Jesmyn': ['Frank'],
    'Eve': ['Grace']
}
​
​
def add_grandchildren(grandparents_dictionary, grandparent, new_grandchildren):
    if grandparent not in grandparents_dictionary:
        # if we haven't seen this grandparent before, add them to the dictionary
        grandparents_dictionary[grandparent] = []
​
    # add the new grandchildren to the grandparent's list of 
    # grandchildren
    current_grandchildren = grandparents_dictionary[grandparent]
    current_grandchildren += new_grandchildren
​
​
def find_grandchildren(parents_dictionary):
    """
    >>> find_grandchildren(SAMPLE_INPUT)
    {'Khaled': ['Frank'], 'Daniel': ['Chibundu', 'Jesmyn', 'Grace']}
    """
    grandparents_dictionary = {}
    for parent in parents_dictionary:
        children = parents_dictionary[parent]
        for child in children:
            if child in parents_dictionary: # check if the child is a parent themselves
                grandchildren = parents_dictionary[child]
                add_grandchildren(grandparents_dictionary,
                                  parent, grandchildren)
    return grandparents_dictionary
                
            

Capstone CS106A Problems


Prime Files

                
def prime_file(filename):
    """
    The given file contains text data on each line as follows.
    Each line is made of a mixture of non-empty alphabetic words
    and non-negative ints, all separated by colons. The numbers can be distinguished
    since their first char is a digit. Lines like this:
    aaa:123:420:xyz:xxx:44:zz:a
    The first element is the "prime" for that line, and is always alphabetic.
    Read through all the lines and build a dict with a key for each prime,
    and its value is a list of all the int number values from all the lines
    with that prime.
    Add every number to the list, even if it is a duplicate.
    When all the data is loaded, print the primes in alphabetical order
    1 per line, each followed by its sorted list of numbers, like this
    aaa [44, 123, 123, 125, 420, 693]
    bbb [16, 23, 101, 101]
    """
    primes = {}
    with open(filename) as f:
        for line in f:
            parts = line.split(':')
            prime = parts[0]
            # pick out which parts are ints - comprehension is cute here
            # or could do this as a regular old for-loop with an append
            # inside is fine and full credit.
            nums = [int(part) for part in parts if part[0].isdigit()]
            if not prime in primes:
                primes[prime] = []
            primes[prime].extend(nums)
    # now output
    for prime in sorted(primes.keys()):
        print(prime, sorted(primes[prime]))
                
            

Dict File

                
def count_zips(filename):
    states = {}
    with open(filename) as f:
        for line in f:
            pass
            words = line.split(',')
            state = words[0]
            if state not in states:   
                states[state] = {}
            counts = states[state]    
            for word in words[1:]:    
                zip = word[:5]        
                if zip not in counts:
                    counts[zip] = 0
                counts[zip] += 1

    for state in sorted(states.keys()):
        print(state)
        counts = states[state]
        for zip in sorted(counts.keys()):
            print(zip, counts[zip])
                
            

Lightning

                
def parse_lightning(filename):
    states = {}
    with open(filename) as f:
        for line in f:
            pass
            words = line.split(',')
            i_state = len(words) - 1
            state = words[i_state].strip() # not grading off: remove \n
            if state not in states:
                states[state] = []
            nums = states[state]            # decomp by var
            for numstr in words[:i_state]:  # omit last elem
                nums.append(int(numstr))
               
    for state in sorted(states.keys()):
        print(state, states[state], sum(states[state]))