From 55081e84a45d32053ad46712a896183a46a20988 Mon Sep 17 00:00:00 2001 From: Jason Neale Date: Sun, 27 Sep 2020 22:36:54 -0400 Subject: [PATCH 1/3] Completed ring_buffer.py --- ring_buffer/doubly_linked_list.py | 165 ++++++++++++++++++++++++++++++ ring_buffer/ring_buffer.py | 28 ++++- 2 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 ring_buffer/doubly_linked_list.py diff --git a/ring_buffer/doubly_linked_list.py b/ring_buffer/doubly_linked_list.py new file mode 100644 index 000000000..ac31627a7 --- /dev/null +++ b/ring_buffer/doubly_linked_list.py @@ -0,0 +1,165 @@ +class ListNode: + def __init__(self, value, prev=None, next=None): + self.prev = prev + self.value = value + self.next = next + +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 + + def add_to_head(self, value): + new_node = ListNode(value) + + self.length += 1 + + if not self.head and not self.tail: + self.head = new_node + self.tail = new_node + else: + new_node.next = self.head + + self.head.prev = new_node + self.head = new_node + + def remove_from_head(self): + value = self.head.value + + if self.head is None and self.tail is None: + return None + + if self.head == self.tail: + self.tail = None + self.head = None + + self.length = 0 + + return value + else: + new_head = self.head.next + new_head.prev = None + + self.length -= 1 + self.head = new_head + + return value + + def add_to_tail(self, value): + new_node = ListNode(value) + + self.length += 1 + + has_no_items = self.head is None and self.tail is None + + if has_no_items: + self.head = new_node + self.tail = new_node + else: + self.tail.next = new_node + + new_node.prev = self.tail + + self.tail = new_node + + def remove_from_tail(self): + has_no_items = self.head is None and self.tail is None + has_one_item = self.head == self.tail + + value = self.tail.value + + if has_no_items: + return None + + if has_one_item: + self.tail = None + self.head = None + self.length = 0 + + return value + else: + previous_node = self.tail.prev + previous_node.next = None + + self.length -= 1 + self.tail = previous_node + + return value + + def move_to_front(self, node): + previous_node = node.prev + next_node = node.next + + if node.prev == None: + return None + + if node.next == None: + previous_node.next = None + + self.tail = previous_node + self.length -= 1 + self.add_to_head(node.value) + else: + previous_node.next = next_node + next_node.prev = previous_node + + self.length -= 1 + self.add_to_head(node.value) + + def move_to_end(self, node): + previous_node = node.prev + next_node = node.next + + if node.next == None: + return None + + if node.prev == None: + next_node.prev = None + + self.head = next_node + self.length -= 1 + self.add_to_tail(node.value) + else: + previous_node.next = next_node + next_node.prev = previous_node + + self.length -= 1 + self.add_to_tail(node.value) + + def delete(self, node): + previous_node = node.prev + next_node = node.next + + value = node.value + + if node.prev == None: + self.remove_from_head() + + return value + + if node.next == None: + self.remove_from_tail() + + return value + else: + previous_node.next = next_node + next_node.prev = previous_node + + self.length -= 1 + + return value + + def get_max(self): + current_node = self.head + max_value = 0 + + while current_node is not None: + if current_node.value > max_value: + max_value = current_node.value + + current_node = current_node.next + return max_value \ No newline at end of file diff --git a/ring_buffer/ring_buffer.py b/ring_buffer/ring_buffer.py index 37e9fb0dd..ad341043f 100644 --- a/ring_buffer/ring_buffer.py +++ b/ring_buffer/ring_buffer.py @@ -1,9 +1,31 @@ +from doubly_linked_list import DoublyLinkedList + + class RingBuffer: def __init__(self, capacity): - pass + self.capacity = capacity + self.current = None + self.storage = DoublyLinkedList() def append(self, item): - pass + if self.storage.length < self.capacity: + self.storage.add_to_tail(item) + self.current = self.storage.tail + + if self.storage.length == self.capacity: + self.current.value = item + + if self.current == self.storage.tail: + self.current = self.storage.head + else: + self.current = self.current.next def get(self): - pass \ No newline at end of file + list_buffer_contents = [] + current_node = self.storage.head + + while current_node: + list_buffer_contents.append(current_node.value) + current_node = current_node.next + + return list_buffer_contents \ No newline at end of file From 14a252313a615dc18c16052a7ff91e685de172dc Mon Sep 17 00:00:00 2001 From: Jason Neale Date: Sun, 27 Sep 2020 22:41:46 -0400 Subject: [PATCH 2/3] Completed reverse.py --- reverse/reverse.py | 19 +++++++++++++++---- reverse/test_reverse.py | 6 +++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/reverse/reverse.py b/reverse/reverse.py index 6116252d1..226beafa5 100644 --- a/reverse/reverse.py +++ b/reverse/reverse.py @@ -18,7 +18,7 @@ def __init__(self): def add_to_head(self, value): node = Node(value) - + if self.head is not None: node.set_next(self.head) @@ -35,8 +35,19 @@ def contains(self, value): return True current = current.get_next() - return False - def reverse_list(self, node, prev): - pass + def reverse_list(self): + if not self.head: + return + + current = self.head + prev = None + + while current: + next_current = current.next_node + current.next_node = prev + prev = current + current = next_current + + self.head = prev \ No newline at end of file diff --git a/reverse/test_reverse.py b/reverse/test_reverse.py index 0199b1a20..9f0a03508 100644 --- a/reverse/test_reverse.py +++ b/reverse/test_reverse.py @@ -20,12 +20,12 @@ def test_contains(self): self.assertFalse(self.list.contains(1000)) def test_empty_reverse(self): - self.list.reverse_list(self.list.head, None) + self.list.reverse_list() self.assertEqual(self.list.head, None) def test_single_reverse(self): self.list.add_to_head(1) - self.list.reverse_list(self.list.head, None) + self.list.reverse_list() self.assertEqual(self.list.head.value, 1) def test_longer_reverse(self): @@ -35,7 +35,7 @@ def test_longer_reverse(self): self.list.add_to_head(4) self.list.add_to_head(5) self.assertEqual(self.list.head.value, 5) - self.list.reverse_list(self.list.head, None) + self.list.reverse_list() self.assertEqual(self.list.head.value, 1) self.assertEqual(self.list.head.get_next().value, 2) self.assertEqual(self.list.head.get_next().get_next().value, 3) From f567faeb18f435e93f3083fe1a0dab5790c42f81 Mon Sep 17 00:00:00 2001 From: Jason Neale Date: Sun, 27 Sep 2020 22:43:38 -0400 Subject: [PATCH 3/3] Completed names.py --- names/binary_search_tree.py | 131 ++++++++++++++++++++++++++++++++++++ names/names.py | 37 ++++++---- 2 files changed, 155 insertions(+), 13 deletions(-) create mode 100644 names/binary_search_tree.py diff --git a/names/binary_search_tree.py b/names/binary_search_tree.py new file mode 100644 index 000000000..67fb2576c --- /dev/null +++ b/names/binary_search_tree.py @@ -0,0 +1,131 @@ +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): + # check if the new nodes value is less than the current nodes value + if value < self.value: + # if there is no left child already here + if not self.left: + # add the new node to the left + # create a BSTNode and encapsulate the value in it then set it to the left + self.left = BSTNode(value) + else: + # otherwise call insert on the left node + return self.left.insert(value) + # otherwise (the new nodes value is greaterthan or equal to the current node value) + if value >= self.value: + # if there is no right child already here + if not self.right: + # add the new node to the right + # create a BSTNode and encapsulate the value in it then set it to the right + self.right = BSTNode(value) + else: + # otherwise call insert on the right node + return self.right.insert(value) + + # Return True if the tree contains the value + # False if it does not + def contains(self, target): + # if the value of the current node matches the target + if target == self.value: + # return True + return True + # check if the target is less than the current nodes value + elif target < self.value: + # if there is no left child already here + if not self.left: + # return False + return False + else: + # return a call of contains on the left child passing in the target value + return self.left.contains(target) + # otherwise (the target is greater than the current nodes value) + elif target > self.value: + # if there is no right child already here + if not self.right: + # return False + return False + else: + # return a call of contains on the right child passing in the target value + return self.right.contains(target) + + # Return the maximum value found in the tree + def get_max(self): + # check for an empty tree + if self.right is None and self.left is None: + # return None + return None + + # check if there is no node to the right + if not self.right: + # return the nodes value + return self.value + else: + # return a call to get max on the right child + return self.right.get_max() + + def for_each(self, fn): + # call the function passing in the current nodes value + fn(self.value) + + # if there is a node to the left + if self.left: + # call the function on the left value + self.left.for_each(fn) + # if there is a node to the right + if self.right: + # call the function on the right node + 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): + pass + + # Print the value of every node, starting with the given node, + # in an iterative breadth first traversal + def bft_print(self): + pass + + # Print the value of every node, starting with the given node, + # in an iterative depth first traversal + def dft_print(self): + pass + + # 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 + +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_dft() +print("post order") +bst.post_order_dft() \ No newline at end of file diff --git a/names/names.py b/names/names.py index ea158997f..e3e717434 100644 --- a/names/names.py +++ b/names/names.py @@ -1,28 +1,39 @@ import time +from binary_search_tree import BSTNode start_time = time.time() -f = open('names_1.txt', 'r') -names_1 = f.read().split("\n") # List containing 10000 names +f = open('names/names_1.txt', 'r') +# List containing 10000 names +names_1 = f.read().split("\n") f.close() -f = open('names_2.txt', 'r') -names_2 = f.read().split("\n") # List containing 10000 names +f = open('names/names_2.txt', 'r') +# List containing 10000 names +names_2 = f.read().split("\n") f.close() -duplicates = [] # Return the list of duplicates in this data structure +duplicates = [] # 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) +root = names_1[0] +names_1_bst = BSTNode(root) + +# loop through +for name in names_1[1:]: + #add names to a binary search tree + names_1_bst.insert(name) + +for name in names_2: + if names_1_bst.contains(name): + duplicates.append(name) 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") # ---------- Stretch Goal ----------- # 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. +# What's the best time you can accomplish? There are no restrictions on techniques or data +# structures, but you may not import any additional libraries that you did not write yourself. \ No newline at end of file