From e75c70fddfd4047bbdc7ff063b09caf8366d5e4f Mon Sep 17 00:00:00 2001 From: Batuhan Balta Date: Fri, 25 Sep 2020 18:33:02 -0700 Subject: [PATCH 1/4] ring_buffer done --- reverse/reverse.py | 1 + ring_buffer/ring_buffer.py | 18 +++++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/reverse/reverse.py b/reverse/reverse.py index 6116252d1..af4d65a0b 100644 --- a/reverse/reverse.py +++ b/reverse/reverse.py @@ -12,6 +12,7 @@ def get_next(self): def set_next(self, new_next): self.next_node = new_next + class LinkedList: def __init__(self): self.head = None diff --git a/ring_buffer/ring_buffer.py b/ring_buffer/ring_buffer.py index 37e9fb0dd..df7597ff4 100644 --- a/ring_buffer/ring_buffer.py +++ b/ring_buffer/ring_buffer.py @@ -1,9 +1,21 @@ class RingBuffer: def __init__(self, capacity): - pass + self.capacity = capacity + self.storage = [] + self.last_item_index = 0 def append(self, item): - pass + if len(self.storage) < self.capacity: + self.storage.append(item) + else: + self.storage[self.last_item_index] = item + self.increase_index() def get(self): - pass \ No newline at end of file + return self.storage + + def increase_index(self): + if self.last_item_index + 1 < self.capacity: + self.last_item_index += 1 + else: + self.last_item_index = 0 From ded4dbd426bcaaf401b756b04c638ea819f9ae72 Mon Sep 17 00:00:00 2001 From: Batuhan Balta Date: Fri, 25 Sep 2020 18:58:57 -0700 Subject: [PATCH 2/4] reverse done --- reverse/reverse.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/reverse/reverse.py b/reverse/reverse.py index af4d65a0b..0494112c5 100644 --- a/reverse/reverse.py +++ b/reverse/reverse.py @@ -16,9 +16,12 @@ def set_next(self, new_next): class LinkedList: def __init__(self): self.head = None + self.tail = None def add_to_head(self, value): node = Node(value) + if self.head is None: + self.tail = node if self.head is not None: node.set_next(self.head) @@ -40,4 +43,10 @@ def contains(self, value): return False def reverse_list(self, node, prev): - pass + if node is None: + return + if node is not self.tail: + self.reverse_list(node.next_node, node) + node.next_node = prev + if node is self.head: + self.head, self.tail = self.tail, self.head From 83c85cc7318afbbcb8af5c22745bcb562bbfef8d Mon Sep 17 00:00:00 2001 From: Batuhan Balta Date: Fri, 25 Sep 2020 20:13:35 -0700 Subject: [PATCH 3/4] names done,sprint challenge done --- names/binary_search_tree.py | 183 ++++++++++++++++++++++++++++++++++++ names/names.py | 27 ++++-- names/queue.py | 21 +++++ names/singly_linked_list.py | 122 ++++++++++++++++++++++++ names/stack.py | 24 +++++ 5 files changed, 371 insertions(+), 6 deletions(-) create mode 100644 names/binary_search_tree.py create mode 100644 names/queue.py create mode 100644 names/singly_linked_list.py create mode 100644 names/stack.py diff --git a/names/binary_search_tree.py b/names/binary_search_tree.py new file mode 100644 index 000000000..a7a4b5632 --- /dev/null +++ b/names/binary_search_tree.py @@ -0,0 +1,183 @@ +""" +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. +""" +from queue import Queue +from stack import Stack + + +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): + # Case 1: value is less than self.value + if value < self.value: + # If there is no left child, insert value here + if self.left is None: + self.left = BSTNode(value) + # ELSE Repeat the process on left subtree + else: + self.left.insert(value) + + # Case 2: value is greater than or equal self.value + elif value >= self.value: + if self.right is None: + 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): + # Case 1: If self.value is equal to the target + if self.value == target: + return True + + # Case 2: if target is less than self.value + if target < self.value: + # if self.left is None, it isn't in the tree + if self.left is None: + return False + else: + return self.left.contains(target) + # Case 3: otherwise + 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 not None: + return self.right.get_max() + else: + return self.value + + # 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, node): + # if the current node is None + # we know we've reached the end of a recursion + # (base case) we want to return + if self is None: + return + + # check if we can "move left" + if self.left is not None: + self.left.in_order_print(self.left) + + # visit the node by printing its value + print(self.value) + + # check if we can "move right" + if self.right is not None: + 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): + + # You should import the queue class from earlier in the + # week and use that class to implement this method + # Use a queue to form a "line" + # for the nodes to "get in" + + # start by placing the root in the queue + + # need a while loop to iterate + # what are we checking in the while statement? + # while length of queue is greater than 0 + # dequeue item from front of queue + # print that item + + # place current item's left node in queue if not None + # place current item's right node in queue if not None + + q = Queue() + q.enqueue(self) + while len(q) > 0: + + dequeued = q.dequeue() + print(dequeued.value) + + if dequeued.left is not None: + q.enqueue(dequeued.left) + if dequeued.right is not None: + q.enqueue(dequeued.right) + + # Print the value of every node, starting with the given node, + # in an iterative depth first traversal + + def dft_print(self, node): + + # initialize an empty stack + # push the root node onto the stack + + # need a while loop to manager our iteration + # if stack is not empty enter the while loop + # pop top item off the stack + # print that item's value + + # if there is a right subtree + # push right item onto the stack + + # if there is a left subtree + # push left item onto the stack + s = Stack() + s.push(self) + + while len(s) > 0: + + popped = s.pop() + print(popped.value) + + if popped.right: + s.push(popped.right) + + if popped.left: + s.push(popped.left) + + # Stretch Goals ------------------------- + # Note: Research may be required + + # Print Pre-order recursive DFT + + def pre_order_dft(self, node): + print(self.value) + + if self.left: + self.left.pre_order_dft(self) + if self.right: + self.right.pre_order_dft(self) + # Print Post-order recursive DFT + + def post_order_dft(self, node): + if self.left: + self.left.post_order_dft(self) + if self.right: + self.right.post_order_dft(self) + + print(self.value) diff --git a/names/names.py b/names/names.py index ea158997f..c2caf306e 100644 --- a/names/names.py +++ b/names/names.py @@ -1,4 +1,5 @@ import time +from binary_search_tree import BSTNode start_time = time.time() @@ -13,14 +14,28 @@ 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) + +first_list = BSTNode(names_1[0]) +next(iter(names_1)) + +for name in names_1: + first_list.insert(name) + +for name in names_2: + if first_list.contains(name): + duplicates.append(name) + + +# for name_1 in names_1: +# for name_2 in names_2: +# if name_1 == name_2: +# duplicates.append(name_1) end_time = time.time() -print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") -print (f"runtime: {end_time - start_time} seconds") +print(f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") +print(f"runtime: {end_time - start_time} seconds") + +# runtime: 0.056012630462646484 seconds # ---------- Stretch Goal ----------- # Python has built-in tools that allow for a very efficient approach to this problem diff --git a/names/queue.py b/names/queue.py new file mode 100644 index 000000000..780fc0b9d --- /dev/null +++ b/names/queue.py @@ -0,0 +1,21 @@ +from singly_linked_list import Node, LinkedList + + +class Queue: + def __init__(self): + self.size = 0 + self.storage = LinkedList() + + def __len__(self): + return self.size + + def enqueue(self, value): + self.size += 1 + self.storage.add_to_tail(value) + return self.storage.tail.get_value() + + def dequeue(self): + if self.size == 0: + return + self.size -= 1 + return self.storage.remove_head() diff --git a/names/singly_linked_list.py b/names/singly_linked_list.py new file mode 100644 index 000000000..6991116f4 --- /dev/null +++ b/names/singly_linked_list.py @@ -0,0 +1,122 @@ +class Node: + # Stores two pieces of data: + # 1. Value + # 2. The Next Node + + # Methods + # 1. Get value + # 2. Set value + # 3. Get next + # 4. Set next + def __init__(self, value=None, next_node=None): + self.value = value + self.next_node = next_node + + def get_value(self): + return self.value + + def set_value(self, new_value): + self.value = new_value + + def get_next(self): + return self.next_node + + def set_next(self, new_next): + self.next_node = new_next + + +class LinkedList: + # 1. Ref to the head Node + # 2. Ref to the tail Node + + def __init__(self): + self.head = None + self.tail = None + + # Behavior + # 1. Append + + def add_to_tail(self, value): + new_tail = Node(value) + if not self.head: # If no head + self.head = new_tail + else: # If there is head + self.tail.set_next(new_tail) + self.tail = new_tail + + # 2. Prepend + + def add_to_head(self, value): + new_head = Node(value) # Create the new head + new_head.set_next(self.head) # Old head becomes the next of new head + if self.head is None: # If there was no item in the list; + self.tail = new_head # Then head and tail becomes the same value + self.head = new_head # Set new head as head anyways + + # 3. Remove Head + + def remove_head(self): + + if not self.head: # No item + return None + + if not self.head.get_next(): # One Item + head = self.head + self.head = None + self.tail = None + return head.get_value() + + value = self.head.get_value() # Multiple items + self.head = self.head.get_next() + return value + + # 4. Remove Tail + + def remove_tail(self): + if not self.head: # No item + return None + + if self.head is self.tail: # One item + value = self.head.get_value() + self.head = None + self.tail = None + return value + + current = self.head # Multiple items + + while current.get_next() is not self.tail: + current = current.get_next() + + value = self.tail.get_value() + self.tail = current + self.tail.set_next(None) + return value + + # 5. Contains? + + def contains(self, value): + if not self.head: # No item + return False + + current = self.head # If there is at least one item + + while current: + if current.get_value() == value: + return True + current = current.get_next() + return False + + # 6. Get Maximum + + def get_max(self): + if not self.head: # No item + return None + + max_value = self.head.get_value() + current = self.head.get_next() + + while current: + if current.get_value() > max_value: + max_value = current.get_value() + current = current.get_next() + return max_value diff --git a/names/stack.py b/names/stack.py new file mode 100644 index 000000000..e71752697 --- /dev/null +++ b/names/stack.py @@ -0,0 +1,24 @@ +from singly_linked_list import LinkedList +import sys +sys.path.append('../singly_linked_list/') + + +class Stack: + def __init__(self): + self.size = 0 + self.storage = LinkedList() + + def __len__(self): + return self.size + + def push(self, value): + value == self.storage.add_to_head(value) + self.size += 1 + return value + + def pop(self): + if self.size == 0: + return None + value = self.storage.remove_head() + self.size -= 1 + return value From 78c62e8da9b5b11170ee6923da03c95d1532d1c9 Mon Sep 17 00:00:00 2001 From: Batuhan Balta Date: Mon, 28 Sep 2020 20:28:31 -0700 Subject: [PATCH 4/4] commit updated --- names/names.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/names/names.py b/names/names.py index c2caf306e..02a0df0dc 100644 --- a/names/names.py +++ b/names/names.py @@ -14,7 +14,7 @@ duplicates = [] # Return the list of duplicates in this data structure # Replace the nested for loops below with your improvements - +# n log(n) first_list = BSTNode(names_1[0]) next(iter(names_1)) @@ -25,7 +25,7 @@ if first_list.contains(name): duplicates.append(name) - +# n*n # for name_1 in names_1: # for name_2 in names_2: # if name_1 == name_2: