ELEX 4653 Lab 2

This lab's exercises deal with functions and container classes.

Version 1. Apr 27, 2019.

Instructions:

  • Modify this notebook by adding the Python code described below.

  • Test your code using the menu item Cell ► Run All

  • Submit the notebook (the .ipynb file) to the appropriate dropbox on the course web site.

Question 1

Write a function called evenitems() that takes one list argument and returns a list. The returned list contains the items from the argument list that have an even length. Use the len() function to determine the length of each list item. For example, evenitems(["abc", (1,2), range(0,4)]) would return: [(1,2),range(0,4)].

In [ ]:
def evenitems(l):
    return [i for i in l if not len(i)%2]
     
evenitems(["abc", (1,2), range(0,4)])

Question 2

Write a function lettersexcept() that takes two string arguments and returns a string containing the letters in the first string that do not appear in the second string. Each letter in the returned string should appear only once. The order of the letters in the output does not matter. For example, lettersexcept("aarddvark","ak") would return "rdv" (or any string with those three letters). Hints: Use sets. The set() constructor can take a string argument. The string method join() can be used to concatenate strings in an iterable object (such as a set).

In [ ]:
def lettersexcept(a,b):
    return ''.join(set(a)-set(b))

lettersexcept("aarddvark","ak")

Question 3

Write a function dict2tuple() that converts a dict argument to a list of tuples where the first element of the tuple is the key and the second is the value. The list can be in any order. For example dict2tuple({'a':1,'xyzzy':73,'foo':2}) would return: [('a', 1), ('xyzzy', 73), ('foo', 2)]. Hint: iterating over a dict returns the keys.

In [ ]:
def dict2tuple(d):
    return [(k,d[k]) for k in d]

dict2tuple({'a':1,'xyzzy':73,'foo':2})

Question 4

Write a function called totalfines() that takes a list argument and returns a dict. The list contains 2-element tuples containing a string and float. The string is a license plate and the number is the amount of a parking fine. The output should be a dict in which the license plates are the keys and the value for each key is the total of all fines for that license plate. For example totalfines([("ABC123",75), ("888XYZ",25), ("ABC123",25)]) would return {"ABC123":100, "888XYZ":25}. Hint: you can use the expression k in d to determine if key k exists in dict d.

In [ ]:
def totalfines(l):
    d={}
    for t in l:
        if t[0] in d:
            d[t[0]]+=t[1]
        else:
            d[t[0]]=t[1]
    return d

totalfines([("ABC123",75), ("888XYZ",25), ("ABC123",25)]) 

Question 5

Write a function idbyvol() that takes a list of 4-tuples and returns a list of strings. The tuples consist of a unique string identifying a sample, and three numbers: $l, w, h$ (length, width and height). The output list should contain the id strings of the samples sorted in order of decreasing volume ($l\times w\times h$). For example, idbyvol([('a2',1,1,1),('b3',1,2,3),('c9',2,1,1)]) would return ['b3', 'c9', 'a2'].

In [ ]:
def idbyvol(l):
    l.sort(key=lambda t:t[1]*t[2]*t[3],reverse=True)
    return [t[0] for t in l]

idbyvol([('a2',1,1,1),('b3',1,2,3),('c9',2,1,1)])

Question 6

Write a function called vowelsused() that takes a list of strings and returns a list with the number of times each vowel was used. The function takes an optional string argument vowels, whose default value is "aeiou", which can be used to define the letters that are considered vowels and the order in which the counts are returned. For example, vowelsused(['abc', 'deef', 'uuffu']) would return [1,2,0,0,3] while vowelsused(['abc', 'deef', 'uuffu'],vowels="af") would return [1,3]. Hint: use a dict with the vowels as keys.

In [ ]:
def vowelsused(l,vowels='aeiou'):
    d={}
    for c in vowels:
        d[c]=0
    for s in l:
        for c in s:
            if c in d:
                d[c]+=1
    return [d[c] for c in vowels]

(vowelsused(['abc', 'deef', 'uuffu']),
 vowelsused(['abc', 'deef', 'uuffu'],vowels="af") )
In [ ]:
# lab validation code; do not modify
def labcheck():
    import random, copy

    def q1():
        l1=[''.join(random.choices("abcdef123456",k=random.randint(1,7))) 
           for i in range(random.randint(1,3))]
        l2=[random.choices(range(1,10),k=random.randint(1,5))
           for i in range(random.randint(1,3))]
        l3=[range(0,random.randint(1,5))
           for i in range(random.randint(1,3))]
        l=l1+l2+l3
        random.shuffle(l)
        le=evenitems(copy.deepcopy(l))
        #print(l,le,sep='\n')
        assert all([(i in le) == (len(i)&1 == 0) for i in l])

    def q2():
        letters="abcdefgh12345"
        s1=''.join(random.choices(letters,k=random.randint(8,16)))
        s2=''.join(random.sample(s1,k=random.randint(3,5)))
        l=lettersexcept(s1,s2)
        #print(''.join(sorted(s1)),''.join(sorted(s2)),l)
        assert ( not len(set(s2) & set(l)) and 
                set(l) & set(s1) == set(l) and
                set(l) | set(s2) == set(s1) )

    def q3():
        l1=[''.join(random.choices("abcdef123",k=random.randint(3,7))) 
           for i in range(random.randint(2,5))]
        l2=[random.randint(0,9) for i in range(len(l1))]
        d={k:v for k,v in zip(l1,l2)}
        # print(l1,l2,d)
        assert sorted(dict2tuple(d)) == sorted([(k,v) for k,v in zip(l1,l2)])  

    def q4():
        l1=[''.join(random.choices("ABCDEFXYZ",k=3)+random.choices("23456",k=3))
            for i in range(random.randint(4,7))]
        l1=random.choices(l1,k=random.randint(4,7))
        l2=list(map(lambda _:25*random.randint(1,7),l1))
        l=[(k,v) for k,v in zip(l1,l2)]
        #print(l1,l2,l)
        f=totalfines(copy.deepcopy(l))
        #print(f)
        assert all([f[k] == sum([t[1] for t in l if t[0] == k]) for k in f])

    def q5():
        n=random.randint(3,5)
        li=[a+b for a,b in zip(random.choices('abcdefghjkmnpqrsuxyz',k=n),
               random.choices('0123456789',k=n))]
        ld=[random.choices(range(1,4),k=3) for _ in range(n)]
        lt=[(i,l,w,d) for i,(l,w,d) in zip(li,ld)]
        l=idbyvol(copy.deepcopy(lt))
        # print(li,ld,lt,l,sep='\n')
        v={t[0]:t[1]*t[2]*t[3] for t in lt}
        # print([v[l[i]] for i in range(len(l))])
        assert all([v[l[i]]>=v[l[i+1]] for i in range(len(l)-1)])

    def q6():
        import re
        for test in [0,1]:
            l=[''.join(random.choices("abcefgijokul",k=random.randint(3,8)))
               for _ in range(random.randint(3,5))]
            s=''.join(l)
            if test == 0:
                v='aeiou'
                n=vowelsused(copy.deepcopy(l))
            else:
                v=random.choices(s,k=random.randint(3,7))
                n=vowelsused(l,vowels=v) 
            # print(l,s,v,n,[len(re.findall(v[i],s)) for i in range(len(v))],sep='\n')
            assert len(n) == len(v),"wrong length"
            assert not any([len(re.findall(v[i],s))-n[i] for i in range(len(v))]),\
                "wrong vowel count(s)"

    for i,s in ((i,'q%d'%i) for i in range(1,20)):
        if s in locals():
            try:
                locals()[s]()
                print("Question {} OK.".format(i))
            except Exception as e:
                print("Failed check for Question {}: {}".format(i,e))

labcheck()