Skip to content
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
11 changes: 11 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true

[dev-packages]

[packages]

[requires]
python_version = "3.8"
102 changes: 102 additions & 0 deletions names/binary_search_tree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from dll_queue import Queue
from dll_stack import Stack


class BinarySearchTree:
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 self.left is None:
self.left = BinarySearchTree(value)
else:
self.left.insert(value)
else:
if self.right is None:
self.right = BinarySearchTree(value)
else:
self.right.insert(value)

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

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

# Call the function `cb` on the value of each node
# You may use a recursive or iterative approach
def for_each(self, cb):
cb(self.value)
if self.left:
self.left.for_each(cb)
if self.right:
self.right.for_each(cb)

# DAY 2 Project -----------------------

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

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

# Print the value of every node, starting with the given node,
# in an iterative depth first traversal
def dft_print(self, node):
stack = Stack()
stack.push(node)
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, node):
pass

# Print Post-order recursive DFT
def post_order_dft(self, node):
pass
20 changes: 20 additions & 0 deletions names/dll_queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from doubly_linked_list import DoublyLinkedList
class Queue:
def __init__(self):
self.size = 0
# Why is our DLL a good choice to store our elements?
self.storage = DoublyLinkedList()

def enqueue(self, value):
self.size += 1
self.storage.add_to_tail(value)

def dequeue(self):
if self.size == 0:
return None
else:
self.size -= 1
return self.storage.remove_from_head()

def len(self):
return self.size
20 changes: 20 additions & 0 deletions names/dll_stack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from doubly_linked_list import DoublyLinkedList
class Stack:
def __init__(self):
self.size = 0
# Why is our DLL a good choice to store our elements?
self.storage = DoublyLinkedList()

def push(self, value):
self.size += 1
self.storage.add_to_head(value)

def pop(self):
if self.size == 0:
return None
else:
self.size -= 1
return self.storage.remove_from_head()

def len(self):
return self.size
139 changes: 139 additions & 0 deletions names/doubly_linked_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
"""Each ListNode holds a reference to its previous node
as well as its next node in the List."""


class ListNode:
def __init__(self, value, prev=None, next=None):
self.value = value
self.prev = prev
self.next = next

"""Wrap the given value in a ListNode and insert it
after this node. Note that this node could already
have a next node it is point to."""
def insert_after(self, value):
current_next = self.next
self.next = ListNode(value, self, current_next)
if current_next:
current_next.prev = self.next

"""Wrap the given value in a ListNode and insert it
before this node. Note that this node could already
have a previous node it is point to."""
def insert_before(self, value):
current_prev = self.prev
self.prev = ListNode(value, current_prev, self)
if current_prev:
current_prev.next = self.prev

"""Rearranges this ListNode's previous and next pointers
accordingly, effectively deleting this ListNode."""
def delete(self):
if self.prev:
self.prev.next = self.next
if self.next:
self.next.prev = self.prev


"""Our doubly-linked list class. It holds references to
the list's head and tail nodes."""


class DoublyLinkedList:
def __init__(self, node=None):
self.head = node
self.tail = node
self.length = 1 if node is not None else 0

def __len__(self):
return self.length

"""Wraps the given value in a ListNode and inserts it
as the new head of the list. Don't forget to handle
the old head node's previous pointer accordingly."""
def add_to_head(self, value):
new_node = ListNode(value)
if self.length == 0:
self.head = new_node
self.tail = new_node
else:
new_node.next = self.head
self.head.prev = new_node
self.head = new_node
self.length += 1

"""Removes the List's current head node, making the
current head's next node the new head of the List.
Returns the value of the removed Node."""
def remove_from_head(self):
value = self.head.value
self.delete(self.head)
return value

"""Wraps the given value in a ListNode and inserts it
as the new tail of the list. Don't forget to handle
the old tail node's next pointer accordingly."""
def add_to_tail(self, value):
new_node = ListNode(value)
if self.length == 0:
self.head = new_node
self.tail = new_node
else:
new_node.prev = self.tail
self.tail.next = new_node
self.tail = new_node
self.length += 1

"""Removes the List's current tail node, making the
current tail's previous node the new tail of the List.
Returns the value of the removed Node."""
def remove_from_tail(self):
value = self.tail.value
self.delete(self.tail)
return value

"""Removes the input node from its current spot in the
List and inserts it as the new head node of the List."""
def move_to_front(self, node):
if self.head is node:
pass
else:
value = node.value
self.delete(node)
self.add_to_head(value)

"""Removes the input node from its current spot in the
List and inserts it as the new tail node of the List."""
def move_to_end(self, node):
if self.tail is node:
pass
else:
value = node.value
self.delete(node)
self.add_to_tail(value)

"""Removes a node from the list and handles cases where
the node was the head or the tail"""
def delete(self, node):
# For now assuming node is in list
node.delete()
self.length -= 1
if self.head is self.tail:
self.head = None
self.tail = None
elif self.head is node:
self.head = node.next
elif self.tail is node:
self.tail = node.prev

"""Returns the highest value currently in the list"""
def get_max(self):
if self.length == 0:
return None
max_value = self.head.value
current_node = self.head
while current_node:
if current_node.value > max_value:
max_value = current_node.value
current_node = current_node.next
return max_value
12 changes: 8 additions & 4 deletions names/names.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@
duplicates = [] # Return the list of duplicates in this data structure

# Replace the nested for loops below with your improvements
for name_1 in names_1:
for name_2 in names_2:
if name_1 == name_2:
duplicates.append(name_1)
from binary_search_tree import BinarySearchTree

tree = BinarySearchTree(names_1[0])
for name_1 in names_1[1:]:
tree.insert(name_1)
for name_2 in names_2:
if tree.contains(name_2):
duplicates.append(name_2)

end_time = time.time()
print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n")
Expand Down
10 changes: 9 additions & 1 deletion reverse/reverse.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,12 @@ def contains(self, value):

def reverse_list(self, node, prev):
# You must use recursion for this solution
pass
if node == None:
return
elif node.get_next() == None:
self.head = node
node.set_next(prev)
return
temp = node.get_next()
node.set_next(prev)
self.reverse_list(temp, node)
25 changes: 22 additions & 3 deletions ring_buffer/ring_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,32 @@ def __init__(self, capacity):
self.storage = DoublyLinkedList()

def append(self, item):
pass
if len(self.storage) == 0:
self.storage.add_to_tail(item)
self.current = self.storage.tail
return

if (len(self.storage)) == self.capacity and self.storage.tail.next is None:
self.storage.tail.next = self.storage.head

if self.storage.tail.next is None:
self.storage.add_to_tail(item)
self.current = self.current.next
else:
self.current = self.current.next
self.current.value = item

def get(self):
# Note: This is the only [] allowed
list_buffer_contents = []

# TODO: Your code here
cursor = self.storage.head
list_buffer_contents.append(cursor.value)
cursor = cursor.next
while cursor is not self.storage.head:
list_buffer_contents.append(cursor.value)
if cursor.next is None:
break
cursor = cursor.next

return list_buffer_contents

Expand Down
Loading