Implement taxicab, which computes the taxicab distance between two intersections using the following data abstraction.
defintersection(st,ave):"""Represent an intersection using the Cantor pairing function."""return (st+ave)*(st+ave+1)//2+ avedefstreet(inter):returnw(inter)-avenue(inter)defavenue(inter):return inter - (w(inter)**2+w(inter)) //2w =lambdaz: int(((8*z+1)**0.5-1)/2)deftaxicab(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 ***"
Q1: Solution
deftaxicab(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 ***"returnabs(street(a) -street(b))+abs(avenue(a) -avenue(b))
Q2: Flatten
Write a function flatten that takes a (possibly deep) list and "flattens" it. For example:
Make sure your solution does not mutate the input list.
defflatten(lst):"""Returns a flattened version of lst.>>> flatten([1, 2, 3]) # normal list [1, 2, 3]>>> x = [1, [2, 3], 4] # deep list>>> flatten(x) [1, 2, 3, 4]>>> x # Ensure x is not mutated [1, [2, 3], 4]>>> x = [[1, [1, 1]], 1, [1, 1]] # deep list>>> flatten(x) [1, 1, 1, 1, 1, 1]>>> x [[1, [1, 1]], 1, [1, 1]] """"*** YOUR CODE HERE ***"
Q2: Solution
defflatten(lst):"""Returns a flattened version of lst.>>> flatten([1, 2, 3]) # normal list [1, 2, 3]>>> x = [1, [2, 3], 4] # deep list>>> flatten(x) [1, 2, 3, 4]>>> x # Ensure x is not mutated [1, [2, 3], 4]>>> x = [[1, [1, 1]], 1, [1, 1]] # deep list>>> flatten(x) [1, 1, 1, 1, 1, 1]>>> x [[1, [1, 1]], 1, [1, 1]] """"*** YOUR CODE HERE ***" flat_lst = []for item in lst:iftype(item)==list: flat_lst +=flatten(item)else: flat_lst += [item]return flat_lst
Q3: Replace Leaf
Define replace_leaf, which takes a tree t, a value old, and a value new. replace_leaf returns a new tree that's the same as t except that every leaf value equal to old has been replaced with new.
defreplace_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 ***"
Q3: Solution
defreplace_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 ***"ifis_leaf(t)andlabel(t)== old: new_label = newelse: new_label =label(t) new_branches = [replace_leaf(b, old, new)for b inbranches(t)]returntree(new_label, new_branches)
Mobiles
Acknowledgements. This mobile example is based on a classic problem from Structure and Interpretation of Computer Programs, Section 2.2.2.
Hint: for more information on this problem (with more pictures!) please refer to this document
A mobile is a type of hanging sculpture. A binary mobile consists of two sides. Each side is a rod of a certain length, from which hangs either a weight or another mobile.
We will represent a binary mobile using the data abstractions below.
A mobile has a left side and a right side.
A side has a positive length and something hanging at the end, either a mobile or weight.
A weight has a positive size
Q4: Weights
We will represent a binary mobile using the data abstractions below.
A mobile has a left side and a right side.
A side has a positive length and something hanging at the end, either a mobile or weight.
A weight has a positive size
defmobile(left,right):"""Construct a mobile from a left side and a right side."""assertis_side(left),"left must be a side"assertis_side(right),"right must be a side"return ['mobile', left, right]defis_mobile(m):"""Return whether m is a mobile."""returntype(m)==listandlen(m)==3and m[0]=='mobile'defleft(m):"""Select the left side of a mobile."""assertis_mobile(m),"must call left on a mobile"return m[1]defright(m):"""Select the right side of a mobile."""assertis_mobile(m),"must call right on a mobile"return m[2]
defside(length,mobile_or_weight):"""Construct a side: a length of rod with a mobile or weight at the end."""assertis_mobile(mobile_or_weight)oris_weight(mobile_or_weight)return ['side', length, mobile_or_weight]defis_side(s):"""Return whether s is a side."""returntype(s)==listandlen(s)==3and s[0]=='side'deflength(s):"""Select the length of a side."""assertis_side(s),"must call length on a side"return s[1]defend(s):"""Select the mobile or weight hanging at the end of a side."""assertis_side(s),"must call end on a side"return s[2]
Implement the weight data abstraction by completing the weight constructor and the size selector so that a weight is represented using a two-element list where the first element is the string 'weight'. The total_weight example is provided to demonstrate use of the mobile, side, and weight abstractions.
defweight(size):"""Construct a weight of some size."""assert size >0"*** YOUR CODE HERE ***"defsize(w):"""Select the size of a weight."""assertis_weight(w),'must call size on a weight'"*** YOUR CODE HERE ***"defis_weight(w):"""Whether w is a weight."""returntype(w)==listandlen(w)==2and w[0]=='weight'
Q4: Solution
defweight(size):"""Construct a weight of some size."""assert size >0"*** YOUR CODE HERE ***"return ['weight', size]defsize(w):"""Select the size of a weight."""assertis_weight(w),'must call size on a weight'"*** YOUR CODE HERE ***"return w[1]
Q5: Balanced
Hint: for more information on this problem (with more pictures!) please refer to this document
Implement the balanced function, which returns whether m is a balanced mobile. A mobile is balanced if two conditions are met:
The torque applied by its left side is equal to that applied by its right side. Torque of the left side is the length of the left rod multiplied by the total weight hanging from that rod. Likewise for the right.
Each of the mobiles hanging at the end of its sides is balanced.
Hint: You may find it helpful to assume that weights themselves are balanced.
defbalanced(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 ***"
Q5: Solution
defbalanced(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 ***"defget_side_torque(side):returnlength(side)*total_weight(end(side))defis_mobile_balanced(m):returnget_side_torque(left(m))==get_side_torque(right(m))ifis_mobile(m):returnis_mobile_balanced(m)andbalanced(end(left(m)))andbalanced(end(right(m)))else:returnTrue
Q6: Totals
Implement totals_tree, which takes a mobile (or weight) and returns a tree whose root is its total weight and whose branches are trees for the ends of the sides.
deftotals_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 ***"
Q6: Solution
deftotals_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 ***"ifis_weight(m):returntree(size(m))else: left_branch =totals_tree(end(left(m))) right_branch =totals_tree(end(right(m)))returntree(total_weight(m), [left_branch, right_branch])