Quiz 3
Contents
Quiz 3#
BEFORE YOU START THIS QUIZ:
Click on “Copy to Drive” to make a copy of the quiz,
Click on “Share”,
Click on “Change” and select “Anyone with this link can edit”
Click “Copy link” and
Paste the link into this Canvas assignment.
This quiz is open notes, open internet. The only thing you can’t do is ask for help.
Copyright 2021 Allen Downey, MIT License
from os.path import basename, exists
def download(url):
filename = basename(url)
if not exists(filename):
from urllib.request import urlretrieve
local, _ = urlretrieve(url, filename)
print('Downloaded ' + local)
download('https://github.com/AllenDowney/DSIRP/raw/main/american-english')
Question 1#
The following is the implementation of a binary search tree (BST) from search.ipynb
.
class Node:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def __repr__(self):
return f'Node({self.data}, {repr(self.left)}, {repr(self.right)})'
class BSTree:
def __init__(self, root=None):
self.root = root
def __repr__(self):
return f'BSTree({repr(self.root)})'
def insert(tree, data):
tree.root = insert_rec(tree.root, data)
def insert_rec(node, data):
if node is None:
return Node(data)
if data < node.data:
node.left = insert_rec(node.left, data)
else:
node.right = insert_rec(node.right, data)
return node
The following cell reads words from a file and adds them to a BST.
But if you run it, you’ll get a RecursionError
.
filename = 'american-english'
tree = BSTree()
for line in open(filename):
for word in line.split():
insert(tree, word.strip())
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
<ipython-input-5-51d6de872b69> in <module>
3 for line in open(filename):
4 for word in line.split():
----> 5 insert(tree, word.strip())
<ipython-input-4-6a6c90da7b3d> in insert(tree, data)
1 def insert(tree, data):
----> 2 tree.root = insert_rec(tree.root, data)
3
4 def insert_rec(node, data):
5 if node is None:
<ipython-input-4-6a6c90da7b3d> in insert_rec(node, data)
9 node.left = insert_rec(node.left, data)
10 else:
---> 11 node.right = insert_rec(node.right, data)
12
13 return node
... last 1 frames repeated, from the frame below ...
<ipython-input-4-6a6c90da7b3d> in insert_rec(node, data)
9 node.left = insert_rec(node.left, data)
10 else:
---> 11 node.right = insert_rec(node.right, data)
12
13 return node
RecursionError: maximum recursion depth exceeded
However, if we put the words into a list, shuffle the list, and then put the shuffled words into the BST, it works.
word_list = []
for line in open(filename):
for word in line.split():
word_list.append(word.strip())
from random import shuffle
shuffle(word_list)
tree = BSTree()
for word in word_list:
insert(tree, word.strip())
Write a few clear, complete sentences to answer the following two questions:
Why did we get a
RecursionError
, and why does shuffling the words fix the problem?
What is the order of growth for the whole process; that is, reading the words into a list, shuffling the list, and then putting the shuffled words into a binary search tree. You can assume that
shuffle
is linear.
Question 2#
As we discussed in class, there are three versions of the search problem:
Checking whether an element is in a collection; for example, this is what the
in
operator does.Finding the index of an element in an ordered collection; for example, this is what the string method
find
does.In a collection of key-value pairs, finding the value that corresponds to a given key; this is what the dictionary method
get
does.
In search.ipynb
, we used a BST to solve the first problem. In this exercise, you will modify it to solve the third problem.
Here’s the code again (although notice that the names of the objects are MapNode
and BSTMap
).
class MapNode:
def __init__(self, data, left=None, right=None):
self.data = data
self.left = left
self.right = right
def __repr__(self):
return f'Node({self.data}, {repr(self.left)}, {repr(self.right)})'
class BSTMap:
def __init__(self, root=None):
self.root = root
def __repr__(self):
return f'BSTMap({repr(self.root)})'
def insert_map(tree, data):
tree.root = insert_map_rec(tree.root, data)
def insert_map_rec(node, data):
if node is None:
return MapNode(data)
if data < node.data:
node.left = insert_map_rec(node.left, data)
else:
node.right = insert_map_rec(node.right, data)
return node
Modify this code so that it stores keys and values, rather than just elements of a collection.
Then write a function called get
that takes a BSTMap
and a key:
If the key is in the map, it should return the corresponding value;
Otherwise it should raise a
KeyError
with an appropriate message.
You can use the following code to test your implementation.
tree_map = BSTMap()
keys = 'uniqueltrs'
values = range(len(keys))
for key, value in zip(keys, values):
print(key, value)
insert_map(tree_map, key, value)
tree_map
u 0
n 1
i 2
q 3
u 4
e 5
l 6
t 7
r 8
s 9
BSTree(MapNode(u, MapNode(n, MapNode(i, MapNode(e, None, None), MapNode(l, None, None)), MapNode(q, None, MapNode(t, MapNode(r, None, MapNode(s, None, None)), None))), MapNode(u, None, None)))
for key in keys:
print(key, get(tree_map, key))
u 0
n 1
i 2
q 3
u 0
e 5
l 6
t 7
r 8
s 9
The following should raise a KeyError
.
get(tree_map, 'b')
Alternative solution#
Modify this code so that it stores keys and values, rather than just elements of a collection.
Then write a function called get
that takes a BSTMap
and a key:
If the key is in the map, it should return the corresponding value;
Otherwise it should raise a
KeyError
with an appropriate message.
You can use the following code to test your implementation.
tree_map = BSTMap()
keys = 'uniqueltrs'
values = range(len(keys))
for key, value in zip(keys, values):
print(key, value)
insert_map(tree_map, key, value)
tree_map
u 0
n 1
i 2
q 3
u 4
e 5
l 6
t 7
r 8
s 9
BSTree(MapNode(('u', 0), MapNode(('n', 1), MapNode(('i', 2), MapNode(('e', 5), None, None), MapNode(('l', 6), None, None)), MapNode(('q', 3), None, MapNode(('t', 7), MapNode(('r', 8), None, MapNode(('s', 9), None, None)), None))), MapNode(('u', 4), None, None)))
for key in keys:
print(key, get(tree_map, key))
u 0
n 1
i 2
q 3
u 0
e 5
l 6
t 7
r 8
s 9