ELEX 4653 Lab 3

Instructions:

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

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

  • Error messages will appear in the output of the last cell of the notebook

  • Submit the notebook (the .ipynb file) to the appropriate dropbox on the course web site.

Version 1 (May 2, 2018)

Q1: Write a recursive function named linearize(l,f) that calls the function f() with the values of all integers in the iterable data structure l. This data structure may contain nested iterable data structures with any level of nesting. For example, if

l=(1,(7,8,(3,2)),((3),1),(5,3))

then linearize(l) would call f() with the values 1, 7, 8, 3, 2, 3, 1, 5, and 3. You can assume l contains only integers and iterable data structures.

This exercise illustrates how a tree can be represented using nested lists. Your algorithm is doing a "depth-first tree walk".

In [1]:
def linearize(l,f):
    if type(l) == int:
        f(l)
    else:
        for i in l:
            linearize(i,f)
            
linearize((1,(7,8,(3,2)),((3),1),(5,3)),lambda x:print(x,end=" "))
1 7 8 3 2 3 1 5 3 

Q2: The min() function finds the smallest value in an iterable. min() can take a key argument that has the same purposeas in the sort() function.

Use min() to write a function, minpos(), that takes a iterator returning tuples and returns the first element of the tuple that has the smallest second element.

For example, minpos([(0,'b'),(1,'a')]) would return 1.

In [2]:
def minpos(x):
    return min(x,key=lambda t:t[1])[0]

minpos([(0,'b'),(1,'a')])
Out[2]:
1

Q3: Write a function myzip() that returns a generator that behaves similarly to the zip() iterator.

myzip() takes two equal-length iterables and returns tuple pairs with one element from each iterable.

For example, print(*myzip([1,2,3],['a','b','c'])) would print:

(1, 'a') (2, 'b') (3, 'c')

In [3]:
def myzip(a,b):
    return (x for x in zip(a,b))
# or:
#   return ((a[i],b[i]) for i in range(min(len(a),len(b))))

print(*myzip([1,2,3],['a','b','c']))
(1, 'a') (2, 'b') (3, 'c')

Q4: Define a function mycos(x) that raises a ValueError exception if the value of x is not between -pi and pi or else returns the cosine of its argument. Write your function below the import statement below. You can use the function math.cos() and the constant math.pi.

In [4]:
import math

def mycos(x):
    if x < -math.pi or x > math.pi:
        raise ValueError
    else:
        return math.cos(x)
    
try:
    mycos(-100)
except:
    pass
mycos(0)
Out[4]:
1.0

Q5: Write a function firstex(l,f) that takes an iterable object l and calls the function f() on each item in that object. Your function should return the first object for which calling f() results in an exception or None if no exceptions are raised.

For example, firstex([0,1,-1,3],math.sqrt) would return -1.

In [5]:
def firstex(l,f):
    for i in l:
        try:
            f(i)
        except:
            return i
        
import math
firstex([0,1,-1,3],math.sqrt)
Out[5]:
-1
In [6]:
# lab validation code; do not modify
def lab3check():
    try:
        Q=1
        from random import randint 
        def treeize(l):
            if len(l) <= 1:
                return l[0]
            else:
                nl=[]
                while len(l)>0:
                    n=randint(1,len(l))
                    nl.append(treeize(l[:n]))
                    l=l[n:]
                return nl

        l=[randint(1,9) for  i in range(randint(8,16))]
        nl=treeize(l)
        ll=[]
        found=lambda x:ll.append(x)
        linearize(nl,found)
        assert l == ll, "linearize({}) result is: {}".format(nl,ll)
        print("Question {} OK.".format(Q))
    except Exception as e:
        print("Failed check for Question {}: {}".format(Q,e))     

    try:
        Q=2
        x=[(a,chr(b)) for a,b in 
           enumerate([randint(ord('a'),ord('z')) for i in range(10)])]
        n=minpos(x)
        assert all([x[i][1] >= x[n][1] for i in range(len(x))])
        print("Question {} OK.".format(Q))
    except Exception as e:
        print("Failed check for Question {}: {}".format(Q,e)) 
        
    try:
        Q=3
        s=str(type(myzip((1,2),(1,2))))
        assert s == "<class 'generator'>", "myzip type:{}".format(s)
        y = list(myzip([i[0] for i in x],[i[1] for i in x]))
        assert x == y, "myzip of {} returns {}".format(x,y)
        print("Question {} OK.".format(Q))
    except Exception as e:
        print("Failed check for Question {}: {}".format(Q,e)) 
        
    try:
        Q=4
        for v,r in [(-4,True),(0,False),(4,True),(3,False)]:
            try:
                failed=False
                mycos(v)
            except:
                failed=True
            assert failed == r, \
                "mycos({}) did {}raise exception".format(v,\
                "" if failed else 'not ')
        print("Question {} OK.".format(Q))
    except Exception as e:
        print("Failed check for Question {}: {}".format(Q,e)) 
        
    try:
        Q=5
        stopat = randint(0,9)        
        def found(i):
            if i == stopat:
                raise StopIteration

        l=[randint(0,9) for i in range(randint(10,20))]
        n=firstex(l,found)
        assert n==stopat or (n == None and stopat not in l), \
            "firstex({}) returned {} instead of {}".format(l,n,stopat)
        print("Question {} OK.".format(Q))
    except Exception as e:
        print("Failed check for Question {}: {}".format(Q,e)) 
        
lab3check()
Question 1 OK.
Question 2 OK.
Question 3 OK.
Question 4 OK.
Question 5 OK.