ELEX 4653 Lab 3

This lab deals with built-in functions, exceptions and generators.

Version 1. May 1, 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

Define a tuple named answer1 containing the built-in functions that return the following:

  • the number of items in an object
  • the smallest of two or more arguments
  • a string that would yield the argument's value when parsed
  • True if all elements of the argument are true

The answer1 tuple should contain [pointers to] the functions, not strings.

In [108]:
answer1=(len,min,repr,all)

Question 2

Write a function named half() that takes one argument and returns an integer with a value of half of the argument's value. It should raise a ValueError exception if the input is not an even-valued integer. For example, half(4) should return 2 but half(1.5), half('a') or half(3) should raise a ValueError exception.

In [109]:
def half(n):
    if type(n) != int or n%2:
        raise ValueError
    else:
        return n//2      

Question 3

Write a function named guess() that takes a function argument, f(), and returns an integer. f() takes one integer argument. If the value passed to f() is less than a secret number, f() raises a TooSmall exception. If the value passed is larger than the secret number then f() raises a TooBig exception. Otherwise f() returns the secret number. The secret number will be a random value between 0 and 999. The guess() function should return the secret number.

In [1]:
# binary search:    
def guess(f):
    n=512
    d=512
    while(d>0):
        try:
            f(n)
        except TooSmall:
            n+=d
        except TooBig:
            n-=d
        else:
            d=0
        d//=2
    return n

# simple approach:
def guess(f):
    for i in range(1000):
        try:
            f(i)
        except:
            continue
        return i

n=314
def myf(i):
    if i>n:
        raise TooBig
    elif i<n:
        raise TooSmall
    else:
        return i
    
guess(myf)
Out[1]:
314

Question 4

Write a generator function named pairs() that takes two arguments. Each argument is a list of strings. The generator yields all possible strings formed by concatenating one string from the first list and one from the second. For example, [s for s in pairs(['a','b'],['1','2','3'])] would result in: ['a1', 'a2', 'a3', 'b1', 'b2', 'b3'].

In [111]:
def pairs(a,b):
    for i in a:
        for j in b:
            yield i+j
In [112]:
# lab validation code; do not modify
def labcheck():

    def checkhash(l,n):
        import hashlib
        # 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 q1():
        import hashlib
        l=repr(answer1)
        #print(hashlib.md5(''.join(l).encode('utf8')).hexdigest())
        checkhash(l,"aef6d31f1c1c6c2b8cb6f7b5562a6d69")

    def q2():
        for t in [1.5, 'a', 3, 4]:
            try:
                half(t)
            except ValueError:
                continue
            if t != 4:
                assert False

    def q3():       
        import random
        global TooSmall, TooBig
        secret=random.randint(0,999)
        class TooSmall(Exception):
            pass
        class TooBig(Exception):
            pass
        def f(n):
            if n<secret:
                raise TooSmall
            if n>secret:
                raise TooBig
            return n

        assert guess(f) == secret   

    def q4():
        import random
        l1=[''.join(random.choices('abcdefghjkmnpqrsuxyz',k=random.randint(1,3))) 
            for i in range(random.randint(2,3))]
        l2=[''.join(random.choices('0123456789',k=random.randint(1,3))) 
            for i in range(random.randint(2,3))]     
        assert repr(type(pairs([],[]))) == "<class 'generator'>"
        assert [s for s in pairs(l1,l2)] == [a+b for a in l1 for b in l2]

    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()
Question 1 OK.
Question 2 OK.
Question 3 OK.
Question 4 OK.