ELEX 4653 Exam 5 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 no errors were found in your answer to question N.

  • Comment out any code that causes errors and re-run Cell ► Run All before submitting your notebook.

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

    Version 3 (corrected marking of Questions 1 and 3 and example in Question 4).

Question 1

Write a function named dictsel that takes an argument named d that is a dictionary. The keys of d are strings and the values are integers with values 0 or 1. Your function should return a list containing the keys of each element for which the value is non-zero. For example, if d={ 'ab': 0, 'def': 1, 'x': 1, 'ABC': 0} then dictsel(d) should return a list containing ['def', 'x'].

In [1]:
def dictsel(d):
    return [k for k in d if d[k]]

d={ 'ab': 0, 'def': 1, 'x': 1, 'ABC': 0}
dictsel(d)
Out[1]:
['def', 'x']

Question 2

Write a function named t2d that takes a list of tuples named l. Your function should create a dictionary by using the first element of each tuple as the key and the value should be a tuple containing the rest of the values. For example if l = [ ('add', 1), ('sub', 2, 32, 16), ('jmp',3,64)] then t2d(l) should return the dictionary {'add': (1,), 'sub': (2, 32, 16), 'jmp': (3, 64)}.

In [2]:
def t2d(l):
    return {t[0]:tuple(t[1:]) for t in l}

l = [ ('add', 1), ('sub', 2, 32, 16), ('jmp',3,64)]
t2d(l)
Out[2]:
{'add': (1,), 'sub': (2, 32, 16), 'jmp': (3, 64)}

Question 3

Write a recursive function named pairup that takes two list arguments named l1 and l2. The function should return a list of tuples where each tuple contains one element from each of the two arguments. For example if l1=[0, 1, 2] and l2=['a', 'b', 'c'] then pairup(l1,l2) would return [(0,'a'), (1,'b'), (2,'c')]. You can assume l1 and l2 are the same length.

In [3]:
def pairup(l1,l2):
    if not l1:
        return []
    else:
        return [(l1[0],l2[0])]+pairup(l1[1:],l2[1:])

# solution that modifies l1, l2
def pairup(l1,l2):
    if not l1:
        return []
    else:
        t = l1.pop(), l2.pop()
        return pairup(l1,l2)+[t]
        
l1=[0, 1, 2]
l2=['a', 'b', 'c']
print(pairup(l1,l2))
print(l1,l2)
[(0, 'a'), (1, 'b'), (2, 'c')]
[] []

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 EL
  2. one of the letters J, K or L
  3. a hyphen (-)
  4. optionally the letter F
  5. one digit
  6. the letters UH
  7. three digits
  8. the letter M

ELJ-F1UH123M

For example, re.search(pat,'ELJ-F1UH123M') would return a match object but re.search(pat,'ELM-F1UH123M') would not.

In [4]:
pat=r'^EL[JKL]-F?\dUH\d{3}M$'

import re
print(re.search(pat,'ELJ-F1UH123M'))
print(re.search(pat,'ELM-F1UH123M'))                
<_sre.SRE_Match object; span=(0, 12), match='ELJ-F1UH123M'>
None
In [5]:
# exam validation code; do not modify
def examcheck():
    import copy, hashlib, re
    from random import randint, choices, shuffle, sample
    
    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(4,6)
        d=dict(zip(randwords(n),[randint(0,1) for i in range(n)]))
        d0=copy.deepcopy(d)
        l=dictsel(d)
        assert len(l) == sum(d0.values()) and \
            all((k in l for k,v in d0.items() if v) ) and \
            all((k not in l for k,v in d0.items() if not v) ), \
                "dictsel({}) returns {}".format(d0,l)

    def q2():       
        n=randint(5,9)
        l=[tuple(randwords(1)+[randint(1,9) for i in range(randint(2,4))]) \
            for j in range(n)]
        l0=copy.copy(l)
        d=t2d(l)
        assert len(d) == n and \
            all([k in [t[0] for t in l0] for k in d]) and \
            all([t[1:] == d[t[0]] for t in l0]), \
            "l2d({}) returns {}".format(l0,d)

    def q3():
        checkrecursive(pairup)
        n=randint(3,5)
        l1=randwords(n)
        l2=[randint(1,9) for _ in range(n)]
        l10,l20=copy.copy(l1),copy.copy(l2)
        l=pairup(l1,l2)
        assert l == [t for t in zip(l10,l20)],"pairup({},{}) returns {}".format(l1,l2,l)
          
  
    def q4():
        ok=['ELJ-F1UH123M', 'ELL-F1UH123M', 'ELJ-1UH123M', 
            'ELJ-F9UH123M', 'ELJ-F1UH999M' ]
        nok=[' ELJ-F1UH123M', 'ELM-F1UH123M','ELJF1UH123M',  
            'ELJ-F.U123M', 'ELJ-F1UH12M', 'ELJ-F1UH123' ]
        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.