ELEX 4653 Exam 4 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.

  • 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 beginswith(d,s) that takes a dict argument d and an string argument s. d has string keys and string values. Your function should return a list of all the values in d for keys that begin with the string s. For example, if d={'hnop': 'iwt', 'ni': 'qmt', 'hnpu': 'vnd'} and s='hn' then bigvals(d,n) should return ['iwt', 'vnd'].

Hint: the string type has a method startswith(). For example "abc".startswith("ab") returns true.

In [1]:
def beginswith(d,s):
    return [v for k,v in d.items() if k.startswith(s)]

d={'hnop': 'iwt', 'ni': 'qmt', 'hnpu': 'vnd'}
   
beginswith(d,'hn')
Out[1]:
['iwt', 'vnd']

Question 2

Write a function named lastone(d) that takes one dict argument named d. Each element of d is a list. Your function should modify d by replacing each list with the last item in that list. For example if d = {'a':[1], 'b':[1,'abc'], 'c':[0,'x',-1]} then after calling lastone(d) the value of d will be {'a': 1, 'b': 'abc', 'c': -1}.

In [2]:
def lastone(d):
    for k,v in d.items():
        d[k]=v[-1]

d =  {'a':[1], 'b':[1,'abc'], 'c':[0,'x',-1]}       
lastone(d)
d
Out[2]:
{'a': 1, 'b': 'abc', 'c': -1}

Question 3

Write a recursive function named lconcat(a,b) that takes two lists of strings, a and b, and returns a list of the concatenation (appending one string to the other) of the corresponding elements of the two lists. You can assume the two lists are the same length. For example if a=['abc', 'de', 'f'] and b=['1', '23', '45'] then lconcat(a,b) would return ['abc1', 'de23', 'f45']. If a and b are empty then lconcat(a,b) returns an empty string.

Hint: use the + operator to join two lists.

In [3]:
def lconcat(a,b):
    if not a:
        return []
    else:
        return [a[0]+b[0]]+lconcat(a[1:],b[1:])
    
a=['abc', 'de', 'f']
b=['1', '23', '45']
lconcat(a,b)
Out[3]:
['abc1', 'de23', 'f45']

Question 4

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

  1. the pattern is found at the start of the string
  2. one of the letters H or S
  3. one of the letters S, B or N
  4. four digits
  5. one of the letters X, Y or Z
  6. the optional letter X
  7. one of the strings -RH or -LH
  8. an optional -V
  9. the pattern is found at the end of the string

For example, re.search(pat,'HS1234XX-RH-V') would return a match object but re.search(pat,'HS123XX-RH-V') would not.

In [4]:
pat=r'^[HS][SBN][0-9]{4}[XYZ]X?-(R|L)H(-V)?$'

import re
re.search(pat,'HS1234XX-RH-V'),re.search(pat,'HS123XX-RH-V')
Out[4]:
(<re.Match object; span=(0, 13), match='HS1234XX-RH-V'>, None)

Marking Code

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 checkrecursive(f):
        s=f.__name__
        assert s in f.__code__.co_names, "{} is not recursive".format(s)
    
    def checkre(pat,ok,nok):
        for s in ok:
            assert re.search(pat,s), \
                f"pattern '{pat}'\n did not match string '{s}'"
        for s in nok:
            assert not re.search(pat,s), \
                f"pattern '{pat}'\n matched string '{s}'"

    def q1():
        n=randint(3,5)
        p=randwords(1)[0]
        k=randwords(n)
        k=[p+i if randint(0,1) else i for i in k]
        v=randwords(n)
        d=dict(zip(k,v))
        l=beginswith(d,p)
        assert l == [a for a,b in 
                     zip( d.values(), [not s.find(p) for s in d.keys()] ) 
                     if b], f'beginswith{d,p}\n returns {l}'

    def q2():
        k=randwords(randint(3,4))
        v=[choices(range(10),k=randint(2,4)) for i in range(randint(2,3))]
        d=dict(zip(k,v))
        d0=copy.deepcopy(d)
        lastone(d)
        assert all([list(reversed(v))[0] == d[k] for k,v in d0.items()]), \
            f'calling lastone{d0}\n results in d={d}'

    def q3():
        checkrecursive(lconcat)
        a=randwords(randint(1,3))
        b=[''.join(map(lambda x:str(x),choices(range(10),k=randint(1,3)))) 
           for s in a]
        a0=copy.deepcopy(a)
        b0=copy.deepcopy(b)
        c=lconcat(a,b)
        assert c == [s[:len(a)]+s[-len(b):] for a,b,s in zip(a0,b0,c)], \
            f'lconcat{a,b} returns {c}'
       
    def q4():
        import re
        ok = [ 'HS1234XX-RH-V','SS1234XX-RH-V','HB1234XX-RH-V',
            'HS1234YX-RH-V','HS1234ZX-RH-V',
            'HS1234X-RH-V','HS1234XX-LH-V','HS1234XX-RH' ]

        nok = [' XS1234XX-RH-V','XS1234XX-RH-V','HX1234XX-RH-V',
            'HS12345XX-RH-V','HS123XX-RH-V','HS1234AX-RH-V',
            'HS1234XY-RH-V','HS1234XX-CH-V','HS1234XX-RH-v',
            'HS1234XX-RH-V_' ]
        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(f"Solution to question {i} may be correct.")
            except Exception as e:
                print(f"Failed check for question {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.