this_file = __file__ def intersection(st, ave): """Represent an intersection using the Cantor pairing function.""" return (st+ave)*(st+ave+1)//2 + ave def street(inter): return w(inter) - avenue(inter) def avenue(inter): return inter - (w(inter) ** 2 + w(inter)) // 2 w = lambda z: int(((8*z+1)**0.5-1)/2) def taxicab(a, b): """Return the taxicab distance between two intersections. >>> times_square = intersection(46, 7) >>> ess_a_bagel = intersection(51, 3) >>> taxicab(times_square, ess_a_bagel) 9 >>> taxicab(ess_a_bagel, times_square) 9 """ "*** YOUR CODE HERE ***" # Mobiles def mobile(left, right): """Construct a mobile from a left side and a right side.""" assert is_side(left), "left must be a side" assert is_side(right), "right must be a side" return ['mobile', left, right] def is_mobile(m): """Return whether m is a mobile.""" return type(m) == list and len(m) == 3 and m[0] == 'mobile' def left(m): """Select the left side of a mobile.""" assert is_mobile(m), "must call left on a mobile" return m[1] def right(m): """Select the right side of a mobile.""" assert is_mobile(m), "must call right on a mobile" return m[2] def side(length, mobile_or_weight): """Construct a side: a length of rod with a mobile or weight at the end.""" assert is_mobile(mobile_or_weight) or is_weight(mobile_or_weight) return ['side', length, mobile_or_weight] def is_side(s): """Return whether s is a side.""" return type(s) == list and len(s) == 3 and s[0] == 'side' def length(s): """Select the length of a side.""" assert is_side(s), "must call length on a side" return s[1] def end(s): """Select the mobile or weight hanging at the end of a side.""" assert is_side(s), "must call end on a side" return s[2] def weight(size): """Construct a weight of some size.""" assert size > 0 "*** YOUR CODE HERE ***" def size(w): """Select the size of a weight.""" assert is_weight(w), 'must call size on a weight' "*** YOUR CODE HERE ***" def is_weight(w): """Whether w is a weight.""" return type(w) == list and len(w) == 2 and w[0] == 'weight' def examples(): t = mobile(side(1, weight(2)), side(2, weight(1))) u = mobile(side(5, weight(1)), side(1, mobile(side(2, weight(3)), side(3, weight(2))))) v = mobile(side(4, t), side(2, u)) return (t, u, v) def total_weight(m): """Return the total weight of m, a weight or mobile. >>> t, u, v = examples() >>> total_weight(t) 3 >>> total_weight(u) 6 >>> total_weight(v) 9 """ if is_weight(m): return size(m) else: assert is_mobile(m), "must get total weight of a mobile or a weight" return total_weight(end(left(m))) + total_weight(end(right(m))) def balanced(m): """Return whether m is balanced. >>> t, u, v = examples() >>> balanced(t) True >>> balanced(v) True >>> w = mobile(side(3, t), side(2, u)) >>> balanced(w) False >>> balanced(mobile(side(1, v), side(1, w))) False >>> balanced(mobile(side(1, w), side(1, v))) False """ "*** YOUR CODE HERE ***" def totals_tree(m): """Return a tree representing the mobile with its total weight at the root. >>> t, u, v = examples() >>> print_tree(totals_tree(t)) 3 2 1 >>> print_tree(totals_tree(u)) 6 1 5 3 2 >>> print_tree(totals_tree(v)) 9 3 2 1 6 1 5 3 2 """ "*** YOUR CODE HERE ***" def replace_leaf(t, old, new): """Returns a new tree where every leaf value equal to old has been replaced with new. >>> yggdrasil = tree('odin', ... [tree('balder', ... [tree('thor'), ... tree('freya')]), ... tree('frigg', ... [tree('thor')]), ... tree('thor', ... [tree('sif'), ... tree('thor')]), ... tree('thor')]) >>> laerad = copy_tree(yggdrasil) # copy yggdrasil for testing purposes >>> print_tree(replace_leaf(yggdrasil, 'thor', 'freya')) odin balder freya freya frigg freya thor sif freya freya >>> laerad == yggdrasil # Make sure original tree is unmodified True """ "*** YOUR CODE HERE ***" def make_fib(): """Returns a function that returns the next Fibonacci number every time it is called. >>> fib = make_fib() >>> fib() 0 >>> fib() 1 >>> fib() 1 >>> fib() 2 >>> fib() 3 >>> fib2 = make_fib() >>> fib() + sum([fib2() for _ in range(5)]) 12 >>> from construct_check import check >>> # Do not use lists in your implementation >>> check(this_file, 'make_fib', ['List']) True """ "*** YOUR CODE HERE ***" def make_withdraw(balance, password): """Return a password-protected withdraw function. >>> w = make_withdraw(100, 'hax0r') >>> w(25, 'hax0r') 75 >>> error = w(90, 'hax0r') >>> error 'Insufficient funds' >>> error = w(25, 'hwat') >>> error 'Incorrect password' >>> new_bal = w(25, 'hax0r') >>> new_bal 50 >>> w(75, 'a') 'Incorrect password' >>> w(10, 'hax0r') 40 >>> w(20, 'n00b') 'Incorrect password' >>> w(10, 'hax0r') "Your account is locked. Attempts: ['hwat', 'a', 'n00b']" >>> w(10, 'l33t') "Your account is locked. Attempts: ['hwat', 'a', 'n00b']" >>> type(w(10, 'l33t')) == str True """ "*** YOUR CODE HERE ***" def make_joint(withdraw, old_password, new_password): """Return a password-protected withdraw function that has joint access to the balance of withdraw. >>> w = make_withdraw(100, 'hax0r') >>> w(25, 'hax0r') 75 >>> make_joint(w, 'my', 'secret') 'Incorrect password' >>> j = make_joint(w, 'hax0r', 'secret') >>> w(25, 'secret') 'Incorrect password' >>> j(25, 'secret') 50 >>> j(25, 'hax0r') 25 >>> j(100, 'secret') 'Insufficient funds' >>> j2 = make_joint(j, 'secret', 'code') >>> j2(5, 'code') 20 >>> j2(5, 'secret') 15 >>> j2(5, 'hax0r') 10 >>> j2(25, 'password') 'Incorrect password' >>> j2(5, 'secret') "Your account is locked. Attempts: ['my', 'secret', 'password']" >>> j(5, 'secret') "Your account is locked. Attempts: ['my', 'secret', 'password']" >>> w(5, 'hax0r') "Your account is locked. Attempts: ['my', 'secret', 'password']" >>> make_joint(w, 'hax0r', 'hello') "Your account is locked. Attempts: ['my', 'secret', 'password']" """ "*** YOUR CODE HERE ***" ## Tree Methods ## def tree(label, branches=[]): """Construct a tree with the given label value and a list of branches.""" for branch in branches: assert is_tree(branch), 'branches must be trees' return [label] + list(branches) def label(tree): """Return the label value of a tree.""" return tree[0] def branches(tree): """Return the list of branches of the given tree.""" return tree[1:] def is_tree(tree): """Returns True if the given tree is a tree, and False otherwise.""" if type(tree) != list or len(tree) < 1: return False for branch in branches(tree): if not is_tree(branch): return False return True def is_leaf(tree): """Returns True if the given tree's list of branches is empty, and False otherwise. """ return not branches(tree) def print_tree(t, indent=0): """Print a representation of this tree in which each node is indented by two spaces times its depth from the root. >>> print_tree(tree(1)) 1 >>> print_tree(tree(1, [tree(2)])) 1 2 >>> numbers = tree(1, [tree(2), tree(3, [tree(4), tree(5)]), tree(6, [tree(7)])]) >>> print_tree(numbers) 1 2 3 4 5 6 7 """ print(' ' * indent + str(label(t))) for b in branches(t): print_tree(b, indent + 1) def copy_tree(t): """Returns a copy of t. Only for testing purposes. >>> t = tree(5) >>> copy = copy_tree(t) >>> t = tree(6) >>> print_tree(copy) 5 """ return tree(label(t), [copy_tree(b) for b in branches(t)]) ################### # Extra Questions # ################### def interval(a, b): """Construct an interval from a to b.""" return [a, b] def lower_bound(x): """Return the lower bound of interval x.""" "*** YOUR CODE HERE ***" def upper_bound(x): """Return the upper bound of interval x.""" "*** YOUR CODE HERE ***" def str_interval(x): """Return a string representation of interval x. """ return '{0} to {1}'.format(lower_bound(x), upper_bound(x)) def add_interval(x, y): """Return an interval that contains the sum of any value in interval x and any value in interval y.""" lower = lower_bound(x) + lower_bound(y) upper = upper_bound(x) + upper_bound(y) return interval(lower, upper) def mul_interval(x, y): """Return the interval that contains the product of any value in x and any value in y.""" p1 = x[0] * y[0] p2 = x[0] * y[1] p3 = x[1] * y[0] p4 = x[1] * y[1] return [min(p1, p2, p3, p4), max(p1, p2, p3, p4)] def sub_interval(x, y): """Return the interval that contains the difference between any value in x and any value in y.""" "*** YOUR CODE HERE ***" def div_interval(x, y): """Return the interval that contains the quotient of any value in x divided by any value in y. Division is implemented as the multiplication of x by the reciprocal of y.""" "*** YOUR CODE HERE ***" reciprocal_y = interval(1/upper_bound(y), 1/lower_bound(y)) return mul_interval(x, reciprocal_y) def par1(r1, r2): return div_interval(mul_interval(r1, r2), add_interval(r1, r2)) def par2(r1, r2): one = interval(1, 1) rep_r1 = div_interval(one, r1) rep_r2 = div_interval(one, r2) return div_interval(one, add_interval(rep_r1, rep_r2)) def multiple_references_explanation(): return """The multiple reference problem...""" def quadratic(x, a, b, c): """Return the interval that is the range of the quadratic defined by coefficients a, b, and c, for domain interval x. >>> str_interval(quadratic(interval(0, 2), -2, 3, -1)) '-3 to 0.125' >>> str_interval(quadratic(interval(1, 3), 2, -3, 1)) '0 to 10' """ "*** YOUR CODE HERE ***"