ELEX 4653 Exam 2 Solutions

Instructions:

  • Answer all four (4) questions.

  • You have 110 minutes to complete the exam.

  • This is an open-book exam. All written material is allowed.

  • No electronic devices other than a flash drive and the lab PC may be used during the exam.

  • No communication with others (electronic, verbal, written or otherwise) is allowed during the exam. Violations will result in a mark of zero and disciplinary action.

  • Add the Python code described below in the cells provided.

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

  • The message "Solution to question N may be correct." at the bottom of the notebook means that your answer to question N may be correct.

  • When the exam time is over, save the notebook (the .ipynb file) and upload it to the appropriate dropbox on the course web site.

Question 1

Write a function named odds that takes a tuple argument named x. Your function should return a (new) list consisting of all the values of x which are odd. For example, if x=(0, 3, 4, 5, 2) your function should return (3, 5).

In [1]:
def odds(x):
    return tuple(i for i in x if i%2)

x=(0, 3, 4, 5, 2)
odds(x)
Out[1]:
(3, 5)

Question 2

Write a function named addlists that takes one dictionary argument named d. The keys of the dictionary d are strings and the values are lists of integers. Your function should create a new dictionary with the same keys and values equal to the sum of the corresponding list. For example if d = { 'a': [3, 1], 'b':[5,8,-1], 'x': [-3,3]} then addlists(d) should return the dictionary { 'a': 4, 'b': 12, 'x':0 }.

In [2]:
def addlists(d):
    return {k:sum(d[k]) for k in d}

d = { 'a': [3, 1], 'b':[5,8,-1], 'x': [-3,3]}
addlists(d)
Out[2]:
{'a': 4, 'b': 12, 'x': 0}

Question 3

Write a recursive function named rbuild that takes an argument named l which is a list of integers. Your function should append values to the list until the list has 5 values. Each call to the function should append one element to the list. The value appended should be the square of the last element to the list. Your function should return the final 5-element list. For example if l=[1,2,3] then rbuild(l) would return [1,2,3,9,81]. You can assume the initial value of the list is not empty and that the last element is larger than 1.

In [3]:
def rbuild(l):
    if len(l) >= 5:
        return l
    else:
        l.append(l[-1]**2)
        return rbuild(l)
        
l=[1,2,3]
rbuild(l)
Out[3]:
[1, 2, 3, 9, 81]

Question 4

Set the variable pat to a regular expression that matches a part number string created according to the following sequence:

  1. the letters AD
  2. the optional letter U
  3. the letter M
  4. the digit 1 or 2
  5. three digits
  6. the letter A or B
  7. the letter R
  8. an optional letter W
  9. the characters Z-RL

For example, re.search(pat,'ADUM1234ARWZ-RL') would return a match object but re.search(pat,'AD1234ARWZ-RL') would not.

In [4]:
pat=r'^ADU?M[12]\d{3}[AB]RW?Z-RL$'

import re
print(re.search(pat,'ADUM1234ARWZ-RL'))
print(re.search(pat,'AD1234ARWZ-RL'))                
<_sre.SRE_Match object; span=(0, 15), match='ADUM1234ARWZ-RL'>
None
In [5]:
# exam validation code; do not modify
def examcheck():
    import copy, hashlib, re
    from random import randint, choices, shuffle
    
    def randwords(n):
        l = set()
        while len(l)<n:
            l |= set((''.join([chr(randint(97,122)) for i in range(randint(2,5))]),))
        return list(l)
    
    def checksorted(l):
        assert all((l[i] <= l[i+1] for i in range(len(l)-1))), \
            "result is not sorted: {}".format(l)

    def checkfunctions(f,l):
        u=[s for s in f.__code__.co_names if s not in l]
        assert not u, "You used the function(s): {}".format(u)
        
    def checkrecursive(f):
        s=f.__name__
        assert s in f.__code__.co_names, "{} is not recursive".format(s)

    def checkhash(l,n):
        # print(hashlib.md5(''.join(l).encode('utf8')).hexdigest())
        assert hashlib.md5(''.join(l).encode('utf8')).hexdigest() == n, \
                'wrong values in list: {} ... {}'.format(l[0],l[-1])
    
    def checkre(pat,ok,nok):
        for s in ok:
            assert re.search(pat,s), \
                "pattern '{}' didn't match string '{}'".format(pat,s)
        for s in nok:
            assert not re.search(pat,s), \
                "pattern '{}' matched string '{}'".format(pat,s)

    def q1():
        n=randint(2,5)
        xe=choices(range(0,100,2),k=n)
        xo=choices(range(1,100,2),k=n)
        x=xe+xo
        shuffle(x)
        y=odds(x)
        assert len(y) == len(xo) and all((i in xo for i in y)), \
            "output is {} for input {}".format(y,x)

    def q2():       
        n=randint(3,5)
        wl=randwords(n)
        nl=[randint(3,5) for i in range(n)]
        d={}
        s={}
        for k,m in zip(wl,nl):
            l=list(range(1,m+1))
            shuffle(l)
            d[k]=l
            s[k]=m*(m+1)/2
        d0=copy.deepcopy(d)
        d=addlists(d)
        assert len(d) == n and all([k in d0 for k in d]) \
            and all([k in d for k in d0]) and all([s[k] == d[k] for k in d]), \
            "after addlists({}) d={}".format(d0,d) 

    def q3():
        checkrecursive(rbuild)
        n=randint(1,3)
        l=[randint(2,5) for i in range(n)]
        l0=copy.copy(l)
        l=rbuild(l)
        no=len(l)
        assert no == 5, "result has length {}".format(no)
        assert (all([l[i]**2 == l[i+1] for i in range(n,4)])), \
            "rbuild({}) returns {}".format(l0,l)
          
  
    def q4():
        ok=['ADUM1234ARWZ-RL', 'ADM1234ARWZ-RL', 'ADUM2111ARWZ-RL', 
            'ADUM1234BRWZ-RL', 'ADUM1234ARZ-RL' ]
        nok=[' ADUM1234ARWZ-RL', 'ADUUM3234ARWZ-RL', 'ADUM12345ARWZ-RL', 
             'ADUM1234CRWZ-RL', 'ADUM1234ARXZ-RL', 'ADUM1234ARWZ-R' ]
        checkre(pat,ok,nok)

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

examcheck()
Solution to question 1 may be correct.
Solution to question 2 may be correct.
Solution to question 3 may be correct.
Solution to question 4 may be correct.