From 2635bb5570cad551c3cebc0dc7c51c7dc4610ae0 Mon Sep 17 00:00:00 2001 From: Richmond Macaspac Date: Fri, 27 Mar 2020 10:39:07 -0500 Subject: [PATCH 1/4] Part1 --- reverse/reverse.py | 10 +++++++++- ring_buffer/ring_buffer.py | 25 ++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/reverse/reverse.py b/reverse/reverse.py index 825d00556..4fc095404 100644 --- a/reverse/reverse.py +++ b/reverse/reverse.py @@ -47,4 +47,12 @@ def contains(self, value): def reverse_list(self, node, prev): # You must use recursion for this solution - pass + if node is None: + return None + if node.next_node is None: + self.head = node + self.head.next_node = prev + return None + else: + self.reverse_list(node.next_node, node) + node.next_node = prev diff --git a/ring_buffer/ring_buffer.py b/ring_buffer/ring_buffer.py index ef88f0d6b..1917062fa 100644 --- a/ring_buffer/ring_buffer.py +++ b/ring_buffer/ring_buffer.py @@ -8,14 +8,25 @@ def __init__(self, capacity): self.storage = DoublyLinkedList() def append(self, item): - pass + if len(self.storage) < self.capacity: + self.storage.add_to_tail(item) + self.current = self.storage.tail + if len(self.storage) == self.capacity: + self.current.value = item + if self.current is self.storage.tail: + self.current = self.storage.head + else: + self.current = self.current.next def get(self): # Note: This is the only [] allowed list_buffer_contents = [] # TODO: Your code here - + current = self.storage.head + while current: + list_buffer_contents.append(current.value) + current = current.next return list_buffer_contents # ----------------Stretch Goal------------------- @@ -23,10 +34,14 @@ def get(self): class ArrayRingBuffer: def __init__(self, capacity): - pass + self.capacity = capacity + self.current = 0 + self.storage = [None] * capacity def append(self, item): - pass + self.current = self.current % self.capacity + self.storage[self.current] = item + self.current += 1 def get(self): - pass + return [i for i in self.storage if i != None] From 00c18e82183ab16e7fdd76605143f8f5e722957a Mon Sep 17 00:00:00 2001 From: Richmond Macaspac Date: Fri, 27 Mar 2020 11:06:00 -0500 Subject: [PATCH 2/4] names --- names/names.py | 78 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/names/names.py b/names/names.py index ea158997f..5a079c1aa 100644 --- a/names/names.py +++ b/names/names.py @@ -1,5 +1,47 @@ import time + +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 and self.left is not None: + return self.left.contains(target) + elif target > self.value and self.right is not None: + return self.right.contains(target) + else: + return False + + # 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() + + start_time = time.time() f = open('names_1.txt', 'r') @@ -13,16 +55,46 @@ duplicates = [] # Return the list of duplicates in this data structure # Replace the nested for loops below with your improvements +# O(n^2) +''' for name_1 in names_1: for name_2 in names_2: if name_1 == name_2: duplicates.append(name_1) - +''' +# Binary search tree: O(n log n) +bst = BinarySearchTree(names_1[0]) +for name in names_1[1:]: + bst.insert(name) +for name in names_2: + if 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. +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 = [] # Return the list of duplicates in this data structure +# O(n), set uses hash table O(1) for read and write so our total time complexity is O(n) +# Space is O(n) too but with a bigger coefficient for the hash table. +names_2_set = set(names_2) +for name in names_1: + if name in names_2_set: + duplicates.append(name) +end_time = time.time() +print( + f"Builtin set: {len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") +print(f"runtime: {end_time - start_time} seconds") From 1120fb18c719a6328c372cfdd607fd9fe72e8eca Mon Sep 17 00:00:00 2001 From: Richmond Macaspac Date: Fri, 27 Mar 2020 11:43:22 -0500 Subject: [PATCH 3/4] all stretch --- names/names.py | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/names/names.py b/names/names.py index 5a079c1aa..95452e3e4 100644 --- a/names/names.py +++ b/names/names.py @@ -1,3 +1,4 @@ +from bisect import bisect_left import time @@ -96,5 +97,39 @@ def get_max(self): duplicates.append(name) end_time = time.time() print( - f"Builtin set: {len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") + f"Builtin set (Fastest): {len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") +print(f"runtime: {end_time - start_time} seconds") + + +# Space efficient stretch +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() +# O(n log n), builtin sort +names_1.sort() + +# Similar to binary search: O(log n) + + +def is_duplicate(main_list, item): + '''check if item in a given sorted list main_list + O(log n ) similar to binary search + ''' + idx = bisect_left(main_list, item) + if idx < len(main_list) and main_list[idx] == item: + return True + return False + + +# total runtime: O(n log n) +duplicates = [n for n in names_2 if is_duplicate(names_1, n)] +end_time = time.time() +print( + f"In-place sort bisect (least storage): {len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") print(f"runtime: {end_time - start_time} seconds") From 24713190cf1e59cb280d0377ed42e1d3751b4dc8 Mon Sep 17 00:00:00 2001 From: Richmond Macaspac Date: Fri, 27 Mar 2020 12:48:55 -0500 Subject: [PATCH 4/4] re-coded bisect --- names/names.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/names/names.py b/names/names.py index 95452e3e4..c06114cde 100644 --- a/names/names.py +++ b/names/names.py @@ -1,7 +1,18 @@ -from bisect import bisect_left import time +def bisect_left(a, x, lo=0, hi=None): + if hi is None: + hi = len(a) + while lo < hi: + mid = (lo+hi)//2 + if a[mid] < x: + lo = mid+1 + else: + hi = mid + return lo + + class BinarySearchTree: def __init__(self, value): self.value = value