Skip to content

Develop #426

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 170 additions & 0 deletions names/binary_search_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
"""
Binary search trees are a data structure that enforce an ordering over
the data they store. That ordering in turn makes it a lot more efficient
at searching for a particular piece of data in the tree.

This part of the project comprises two days:
1. Implement the methods `insert`, `contains`, `get_max`, and `for_each`
on the BSTNode class.
2. Implement the `in_order_print`, `bft_print`, and `dft_print` methods
on the BSTNode class.
"""
class Stack:
def __init__(self):
self.storage = []

def __len__(self):
return len(self.storage)

def push(self, value):
self.storage.append(value)

def pop(self):
if len(self.storage) == 0:
return None
return self.storage.pop()

def peek(self):
return self.storage[-1]

class Queue:
def __init__(self):
self.storage = []

def __len__(self):
return len(self.storage)

def enqueue(self, value):
self.storage.append(value)

def dequeue(self):
if len(self.storage) == 0:
return None
return self.storage.pop(0)


class BSTNode:
def __init__(self, value):
self.value = value
self.left = None
self.right = None

# Insert the given value into the tree
def insert(self, value):
if value < self.value:
if not self.left:
self.left = BSTNode(value)
else:
self.left.insert(value)
elif value >= self.value:
if not self.right:
self.right = BSTNode(value)
else:
self.right.insert(value)

# Return True if the tree contains the value
# False if it does not
def contains(self, target):
if target == self.value:
return True
elif target < self.value:
if not self.left:
return False
else:
return self.left.contains(target)
elif target > self.value:
if not self.right:
return False
else:
return self.right.contains(target)

# Return the maximum value found in the tree
def get_max(self):
if not self.value:
return None
if not self.right:
return self.value
else:
return self.right.get_max()

# Call the function `fn` on the value of each node
def for_each(self, fn):
fn(self.value)
if self.left:
self.left.for_each(fn)
if self.right:
self.right.for_each(fn)

# Part 2 -----------------------

# Print all the values in order from low to high
# Hint: Use a recursive, depth first traversal
def in_order_print(self):
if self.left:
self.left.in_order_print()

print(self.value)

if self.right:
self.right.in_order_print()

# Print the value of every node, starting with the given node,
# in an iterative breadth first traversal
def bft_print(self):
queue = Queue()
queue.enqueue(self)
while queue.__len__() > 0:
node = queue.dequeue()
print(node.value)
if (node.left):
queue.enqueue(node.left)
if (node.right):
queue.enqueue(node.right)

# Print the value of every node, starting with the given node,
# in an iterative depth first traversal
def dft_print(self):
stack = Stack()
stack.push(self)
while stack.__len__() > 0:
node = stack.pop()
print(node.value)
if(node.left):
stack.push(node.left)
if(node.right):
stack.push(node.right)

# Stretch Goals -------------------------
# Note: Research may be required

# Print Pre-order recursive DFT
def pre_order_dft(self):
pass

# Print Post-order recursive DFT
def post_order_dft(self):
pass

"""
This code is necessary for testing the `print` methods
"""
bst = BSTNode(1)

bst.insert(8)
bst.insert(5)
bst.insert(7)
bst.insert(6)
bst.insert(3)
bst.insert(4)
bst.insert(2)

bst.bft_print()
bst.dft_print()

# print("elegant methods")
# print("pre order")
# bst.pre_order_dft()
print("in order")
bst.in_order_print()
# print("post order")
# bst.post_order_dft()
36 changes: 33 additions & 3 deletions names/names.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import time
from binary_search_tree import BSTNode

start_time = time.time()

Expand All @@ -13,10 +14,22 @@
duplicates = [] # Return the list of duplicates in this data structure

# Replace the nested for loops below with your improvements

bst = BSTNode('M')

for name_1 in names_1:
for name_2 in names_2:
if name_1 == name_2:
duplicates.append(name_1)
bst.insert(name_1)

for name_2 in names_2:
if bst.contains(name_2):
duplicates.append(name_2)

# for name_1 in names_1:
# for name_2 in names_2:
# if name_1 == name_2:
# duplicates.append(name_1)

# Runtime complexity is O(n^2) prior to optimization

end_time = time.time()
print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n")
Expand All @@ -26,3 +39,20 @@
# Python has built-in tools that allow for a very efficient approach to this problem
# What's the best time you can accomplish? Thare are no restrictions on techniques or data
# structures, but you may not import any additional libraries that you did not write yourself.


start_time = time.time()

f = open('names_1.txt', 'r')
names_1 = f.read().split("\n") # List containing 10000 names
f.close()

f = open('names_2.txt', 'r')
names_2 = f.read().split("\n") # List containing 10000 names
f.close()

duplicates = set(names_1).intersection(names_2)

end_time = time.time()
print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n")
print (f"runtime: {end_time - start_time} seconds")
6 changes: 5 additions & 1 deletion reverse/reverse.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@ def contains(self, value):
return False

def reverse_list(self, node, prev):
pass
if node is None:
self.head = prev
return
self.reverse_list(node.get_next(), node)
node.set_next(prev)
37 changes: 34 additions & 3 deletions ring_buffer/ring_buffer.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,40 @@
class RingBuffer:
def __init__(self, capacity):
pass
self.capacity = capacity
self.storage = []
self.oldest_index = 0


def append(self, item):
pass
if len(self.storage) < self.capacity:
self.storage.append(item)
else:
self.storage[self.oldest_index] = item
if self.oldest_index < len(self.storage) - 1:
self.oldest_index += 1
else:
self.oldest_index = 0

def get(self):
pass
return self.storage


# buffer = RingBuffer(3)

# buffer.get() # should return []

# buffer.append('a')
# buffer.append('b')
# buffer.append('c')

# buffer.get() # should return ['a', 'b', 'c']

# # 'd' overwrites the oldest value in the ring buffer, which is 'a'
# buffer.append('d')

# buffer.get() # should return ['d', 'b', 'c']

# buffer.append('e')
# buffer.append('f')

# buffer.get() # should return ['d', 'e', 'f']