ELEX 4653 Lab 1¶

The lab provides practice creating built-in types.

Instructions:

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

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

  • Save the notebook (the .ipynb file) and upload it to the appropriate Assignment folder on the course web site.

Question 1¶

Create a list named mylist containing the following:

  1. a string that is your BCIT ID. For example "A00123456".
  2. an integer equal to the digits of your ID (everything following the A)
  3. a float equal to the integer above divided by 123
  4. a string equal to your BCIT ID with the characters in reverse order
  5. a bool that is True if the integer above is divisible by 3

For example, if your BCIT ID were A00123456 then mylist would equal ["A00123456", 123456, 1003.7073170731708, '65432100A', True]

In [6]:
s='A00123456'
i=int(s[1:])
f=i/123
rs=s[::-1]
b=not bool(i%3)
# mylist=[s, i, f, rs, b]
mylist=[s, i, f, rs, b]
# mylist=[s, i, f, rs, not b]

mylist = ["A00123456", 123456, 1003.7073170731708, '65432100A', True]

Question 2¶

Create a string named myname containing your first name. Use a variant that is three or more letters long.

Create a dictionary named mydict that contains one entry for each unique letter of your name with the position in your name where that letter first occurs. For example if you name is 'Betty' then you would set mydict = { 'B':0, 'e':1, 't':2, 'y':4 }.

In [7]:
myname="Betty"
mydict = { 'B':0, 'e':1, 't':2, 'y':4 }    
# mydict = {'B':0}
ydict = { 'B':0, 'e':1, 't':2, 'y':4 }
mydict
Out[7]:
{'B': 0, 'e': 1, 't': 2, 'y': 4}

Question 3¶

Create a set of complex numbers, myset where each element is equal to a+jb where a and b are successive digits from your BCIT ID.

For example if you ID is A00123456 then myset = { 0+0j, 1+2j, 3+4j, 5+6j }.

In [8]:
myset = set([complex(float(s[i]),float(s[i+1])) for i in range(1,9,2)])
# myset = {}
myset = { 0+0j, 1+2j, 3+4j, 5+6j }
myset
Out[8]:
{(1+2j), (3+4j), (5+6j), 0j}
In [12]:
# lab validation code; do not modify
def labcheck(testing=0,ntest=10):
    '''
    Python exercise checking.
    Ed.Casas 2023-5-22
    Calls functions q<n>* and checks HMAC of return value[0].
    On mismatch prints return value[1] (function, arguments and return values).
    Setting testing=1 prints HMACs of correct results; paste into 'hashvalues'.
    Note:
    If q<n>* result not JSON-able, convert to string.
    Result order matters for comparison. Sort result if ordering not important.
    '''
    
    import base64, copy, hashlib, json, random, re, string, types 
    from random import randint
    
    # compare regex to strings that should/shouldn't match
    def checkre(pat,ok,nok):
        for s in ok:
            assert re.fullmatch(pat,s), \
                f"pattern '{pat}'\n did not match string '{s}'"
        for s in nok:
            assert not re.fullmatch(pat,s), \
                f"pattern '{pat}'\n matched string '{s}'"  
    
    # list of n words with nl letters from chars without repeats
    def randwords(n,chars=string.ascii_lowercase,nl=(2,5)):
        l = []
        while len(l)<n:
            w = ''.join([chars[randint(0,len(chars)-1)] for i in range(randint(*nl))])
            if w not in l:
                l.append(w)
        return l
    
    # convert sets to dicts and dict keys to strings so they can be sorted
    def orderkeys(o):
        if isinstance(o,set):
            return {str(k):None for k in o}
        if isinstance(o,dict):
            return {str(k):orderkeys(v) for k,v in o.items()}
        return o
    
    def q1a():
        r = len(mylist)
        return r, f"wrong number of values in mylist={r}"
    
    def q1b():
        t = [str(type(x)) for x in mylist]
        return t, f"mylist has types {t}"
    
    def q1c():
        s,i,f,rs,b = mylist
        return ['A'+str("%08d"%i) == s,
            abs(f*123 - i) < 0.1,
            [s[i] == rs[8-i] for i in range(8)],
            b == ((i//3)*3 - i == 0)], \
            f"mylist = {mylist}" 

    def q2():
        return len(myname) >= 3 and \
            len(mydict) == len(set(myname)) and \
            all([myname[mydict[c]] == c for c in set(myname)]), \
            f"for myname='{myname}', mydict=f{mydict}"


    def q3():
        s = mylist[0]
        return not set([("%d"%(c.real),"%d"%(c.imag)) for c in myset]) ^ \
            set(tuple(zip(s[1:-1:2],s[2::2]))), \
            f"myset={myset} for mylist[0] = {s}"

    hashvalues = '''
LgOn
rPFO
jGA9
sifm
sifm
'''.split()

    newhash = ''
    dsize = 3 # HMAC base64 digest size (bytes, use 3 or 6 for 4 or 8 char digests)
    dlen = ((dsize*8+5)//6+3)//4*4
           
    for n,f in [(n,f) for n,f in locals().items() if callable(f) and re.search(r'^[Qq]\d+.*',n)]:
        random.seed(n)      
        hashes = '0'*dlen*ntest if testing else hashvalues.pop(0)
        err = ''
        while hashes and not err:
            h, hashes = hashes[:dlen], hashes[dlen:] 
            try:
                v,s = f()
                b = json.dumps(orderkeys(v),sort_keys=True).encode()
                c = base64.b64encode(hashlib.blake2b(b,digest_size=dsize).digest()).decode()
                if testing:
                    print(s)
                    newhash += c
                else:
                    if c != h:
                        err = f"Wrong result for test {n}: {s} (HMAC={c} instead of {h})"
            except Exception as e:
                err = f"Error during test {n}: {e}"               
        if testing:
            newhash += '\n'
        else:
            print(err or f"Passed test {n}.")
            
    if testing:
        print(newhash)

labcheck()
Passed test q1a.
Passed test q1b.
Passed test q1c.
Passed test q2.
Passed test q3.
In [ ]: