Skip to content

Commit 39e5356

Browse files
authored
Merge pull request #1 from fuston05/scott-fuston
imports doubly_linked_list as storage, creates method 'append' to Rin…
2 parents f927656 + 5a9a96e commit 39e5356

File tree

5 files changed

+243
-12
lines changed

5 files changed

+243
-12
lines changed

Pipfile

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[[source]]
2+
name = "pypi"
3+
url = "https://pypi.org/simple"
4+
verify_ssl = true
5+
6+
[dev-packages]
7+
8+
[packages]
9+
10+
[requires]
11+
python_version = "3.8"

names/binary_search_tree.py

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
2+
# Binary search trees are a data structure that enforce an ordering over
3+
# the data they store. That ordering in turn makes it a lot more efficient
4+
# at searching for a particular piece of data in the tree.
5+
6+
# This part of the project comprises two days:
7+
# 1. Implement the methods `insert`, `contains`, `get_max`, and `for_each`
8+
# on the BSTNode class.
9+
# 2. Implement the `in_order_print`, `bft_print`, and `dft_print` methods
10+
# on the BSTNode class.
11+
12+
13+
14+
class BSTNode:
15+
def __init__(self, value):
16+
self.value = value
17+
self.left = None
18+
self.right = None
19+
20+
# Insert the given value into the tree
21+
def insert(self, value):
22+
# compare the value to the root's value to determine which direction
23+
# we're gonna go in
24+
# if the value < root's value
25+
if value < self.value:
26+
# go left
27+
# how do we go left?
28+
# we have to check if there is another node on the left side
29+
if self.left:
30+
# then self.left is a Node
31+
# now what?
32+
self.left.insert(value)
33+
else:
34+
# then we can park the value here
35+
self.left = BSTNode(value)
36+
# else the value >= root's value
37+
else:
38+
# go right
39+
# how do we go right?
40+
# we have to check if there is another node on the right side
41+
if self.right:
42+
# then self.right is a Node
43+
self.right.insert(value)
44+
else:
45+
self.right = BSTNode(value)
46+
47+
# Return True if the tree contains the value
48+
# False if it does not
49+
def contains(self, target):
50+
currentNode = self
51+
# if current node is too big
52+
if currentNode.value > target:
53+
# go left
54+
if currentNode.left:
55+
# increment the currentNode
56+
currentNode = currentNode.left
57+
# return for recursion to work
58+
return currentNode.contains(target)
59+
elif currentNode.value < target:
60+
# go right
61+
if currentNode.right:
62+
# increment the currentNode
63+
currentNode = currentNode.right
64+
# return for recursion to work
65+
return currentNode.contains(target)
66+
elif currentNode.value == target:
67+
# we have a match
68+
return True
69+
# if no match found
70+
else:
71+
return False
72+
73+
# Return the maximum value found in the tree
74+
75+
def get_max(self):
76+
if not self.right:
77+
return self.value
78+
return self.right.get_max()
79+
80+
# Call the function `fn` on the value of each node
81+
def for_each(self, fn):
82+
# current node
83+
currentNode = self
84+
fn(currentNode.value)
85+
if self.left:
86+
nextLeft = self.left
87+
nextLeft.for_each(fn)
88+
if self.right:
89+
nextRight = self.right
90+
nextRight.for_each(fn)
91+
92+
# Part 2 -----------------------
93+
94+
# Print all the values in order from low to high
95+
# Hint: Use a recursive, depth first traversal
96+
97+
def in_order_print(self, node=None):
98+
# everything will get printed... so..
99+
100+
# if self has a 'left', self is BIGGER
101+
if self.left:
102+
self.left.in_order_print(self)
103+
104+
print(self.value)
105+
106+
# if self has a 'right', self is SMALLER
107+
if self.right:
108+
self.right.in_order_print(self)
109+
110+
# Print the value of every node, starting with the given node,
111+
# in an iterative breadth first traversal FIFO
112+
113+
def bft_print(self, node=None):
114+
Que = []
115+
Que.append(self)
116+
117+
while len(Que) > 0:
118+
current = Que.pop(0)
119+
print(current.value)
120+
121+
if current.left:
122+
Que.append(current.left)
123+
124+
if current.right:
125+
Que.append(current.right)
126+
127+
# Print the value of every node, starting with the given node,
128+
# in an iterative depth first traversal LIFO
129+
def dft_print(self, node=None):
130+
stack= []
131+
stack.append(self)
132+
133+
while len(stack) > 0:
134+
current= stack.pop(len(stack)-1)
135+
print(current.value)
136+
137+
if current.right:
138+
stack.append(current.right)
139+
if current.left:
140+
stack.append(current.left)
141+
142+
# Stretch Goals -------------------------
143+
# Note: Research may be required
144+
145+
# Print Pre-order recursive DFT
146+
def pre_order_dft(self, node):
147+
pass
148+
149+
# Print Post-order recursive DFT
150+
def post_order_dft(self, node):
151+
pass
152+
153+
154+
# bst = BSTNode(1)
155+
# bst.insert(8)
156+
# bst.insert(5)
157+
# bst.insert(7)
158+
# bst.insert(6)
159+
# bst.insert(3)
160+
# bst.insert(4)
161+
# bst.insert(2)
162+
163+
# bst.bft_print()

names/names.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import time
2-
2+
from binary_search_tree import BSTNode
33
start_time = time.time()
44

55
f = open('names_1.txt', 'r')
@@ -10,17 +10,35 @@
1010
names_2 = f.read().split("\n") # List containing 10000 names
1111
f.close()
1212

13+
# build names list 1: **** O(n) ****
14+
count = 0
15+
for n in names_1:
16+
if count == 0:
17+
list_1_names = BSTNode(n)
18+
count += 1
19+
else:
20+
list_1_names.insert(n)
21+
count += 1
22+
1323
duplicates = [] # Return the list of duplicates in this data structure
1424

1525
# Replace the nested for loops below with your improvements
16-
for name_1 in names_1:
17-
for name_2 in names_2:
18-
if name_1 == name_2:
19-
duplicates.append(name_1)
26+
27+
# **** runtime: O(n^C), quadric (11.5 on my machine) ****
28+
# for name_1 in names_1:
29+
# for name_2 in names_2:
30+
# if name_1 == name_2:
31+
# duplicates.append(name_1)
32+
33+
# **** O(Log n) ****
34+
for n in names_2:
35+
if list_1_names.contains(n):
36+
duplicates.append(n)
37+
2038

2139
end_time = time.time()
22-
print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n")
23-
print (f"runtime: {end_time - start_time} seconds")
40+
print(f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n")
41+
print(f"runtime: {end_time - start_time} seconds")
2442

2543
# ---------- Stretch Goal -----------
2644
# Python has built-in tools that allow for a very efficient approach to this problem

ring_buffer/ring_buffer.py

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,46 @@
1+
from doubly_linked_list import DoublyLinkedList
2+
3+
14
class RingBuffer:
25
def __init__(self, capacity):
3-
pass
6+
self.capacity = capacity
7+
self.storage = DoublyLinkedList()
8+
self.lastOverwrittenNode = None
49

510
def append(self, item):
6-
pass
11+
# check cap
12+
if len(self.storage) < self.capacity:
13+
# if less than cap, add to end
14+
self.storage.add_to_tail(item)
15+
else:
16+
if len(self.storage) == self.capacity:
17+
# if cap is full, but nothing new has been added yet
18+
if self.lastOverwrittenNode == None:
19+
self.storage.remove_from_head()
20+
self.storage.add_to_head(item)
21+
# set lastOverwrittenNode
22+
self.lastOverwrittenNode = self.storage.head
23+
# cap == full, things have been added
24+
else:
25+
# if tail was last one to be overwritten
26+
if self.lastOverwrittenNode == self.storage.tail:
27+
# set head to be next to get overwritten
28+
self.lastOverwrittenNode = self.storage.head
29+
self.lastOverwrittenNode.value = item
30+
else:
31+
# if tail was not last to be overwritten,
32+
# overwrite "next"
33+
self.lastOverwrittenNode = self.lastOverwrittenNode.next
34+
self.lastOverwrittenNode.value = item
735

836
def get(self):
9-
pass
37+
# return all elements values that are not None
38+
# returns as a list in given order
39+
data_list = []
40+
currentNode = self.storage.head
41+
42+
while currentNode is not None:
43+
if currentNode.value is not None:
44+
data_list.append(currentNode.value)
45+
currentNode = currentNode.next
46+
return data_list

ring_buffer/test_ring_buffer.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import unittest
22
from ring_buffer import RingBuffer
33

4+
45
class RingBufferTests(unittest.TestCase):
56
def setUp(self):
67
self.capacity = 5
78
self.buffer = RingBuffer(self.capacity)
8-
9+
910
def test_new_buffer_has_appropriate_capacity(self):
1011
self.assertEqual(self.buffer.capacity, self.capacity)
1112

@@ -48,5 +49,6 @@ def test_adding_50_elements_to_buffer(self):
4849

4950
self.assertEqual(self.buffer.get(), [45, 46, 47, 48, 49])
5051

52+
5153
if __name__ == '__main__':
52-
unittest.main()
54+
unittest.main()

0 commit comments

Comments
 (0)