From 107b4e9f149ec582629e3c58c67b5183ec985c92 Mon Sep 17 00:00:00 2001 From: Asher Kobin Date: Fri, 15 May 2020 14:01:00 -0400 Subject: [PATCH 1/4] MVP Maybe --- names/names.py | 86 ++++++++++++++++++++-- ring_buffer/ring_buffer.py | 143 +++++++++++++++++++++++++++++++++++-- 2 files changed, 219 insertions(+), 10 deletions(-) diff --git a/names/names.py b/names/names.py index ea158997f..0513bb026 100644 --- a/names/names.py +++ b/names/names.py @@ -1,4 +1,68 @@ import time +""" +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 collections import deque +class BSTNode: + def __init__(self, value): + self.value = value + self.left = None + self.right = None + + def insert(self, value): + if value < self.value: + if self.left is None: + self.left = BSTNode(value) + else: + return self.left.insert(value) + elif value >= self.value: + if self.right is None: + self.right = BSTNode(value) + else: + return self.right.insert(value) + + def contains(self, target): + if self.value == target: + return True + if target < self.value: + if self.left is None: + return False + return self.left.contains(target) + if target > self.value: + if self.right is None: + return False + return self.right.contains(target) + + def get_max(self): + if not self.right: + return self.value + return self.right.get_max() + + def for_each(self, fn): + fn(self.value) + if self.left is not None: + self.left.for_each(fn) + if self.right is not None: + self.right.for_each(fn) + return + + def in_order_print(self, node): + if node: + self.in_order_print(node.left) + print(node.value) + self.in_order_print(node.right) + + + + start_time = time.time() @@ -6,17 +70,31 @@ names_1 = f.read().split("\n") # List containing 10000 names f.close() +bst1 = BSTNode("") +for name in names_1: + bst1.insert(name) + f = open('names_2.txt', 'r') names_2 = f.read().split("\n") # List containing 10000 names f.close() +bst2 = BSTNode("") +for name in names_2: + bst2.insert(name) + 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) +# for name_1 in names_1: +# for name_2 in names_2: +# if name_1 == name_2: +# duplicates.append(name_1) + +def compare(x): + if bst2.contains(x): + duplicates.append(x) + +bst1.for_each(lambda x: compare(x)) end_time = time.time() print (f"{len(duplicates)} duplicates:\n\n{', '.join(duplicates)}\n\n") diff --git a/ring_buffer/ring_buffer.py b/ring_buffer/ring_buffer.py index 37e9fb0dd..dea87e57d 100644 --- a/ring_buffer/ring_buffer.py +++ b/ring_buffer/ring_buffer.py @@ -1,9 +1,140 @@ +class Node: + def __init__(self, value): + self.value = value + self.next = None + +class LinkedList: + def __init__(self): + self.head = None + self.tail = None + self.length = 0 + + def __len__(self): + return self.length + + def contains(self, value): + result = False + cur = self.head + while cur != None: + if cur.value == value: + result = True + break + cur = cur.next + return result + + def get_max(self): + max = None + cur = self.head + while cur != None: + if cur.value > max: + max = cur.value + cur = cur.next + return max + + def add_to_tail(self, value): + new_node = Node(value) + if self.head == None: + self.head = new_node + self.tail = new_node + else: + self.tail.next = new_node + self.tail = new_node + self.length += 1 + + def remove_head(self): + if self.head == None: + return None + else: + if self.head == self.tail: + self.tail = None + value = self.head.value + self.head = self.head.next + self.length -= 1 + return value + class RingBuffer: - def __init__(self, capacity): - pass + def __init__(self, capacity): + self.capacity = capacity + self.storage = LinkedList() + self.oldest_item = None + + def append(self, item): + if len(self.storage) == 0: + self.oldest_item = Node(item) + self.storage.head = self.oldest_item + self.storage.length += 1 + elif self.capacity > len(self.storage): + new_node = Node(item) + node = self.storage.head + while node: + if node.next is None: + node.next = Node(item) + self.oldest_item = self.oldest_item + self.storage.length += 1 + break + node = node.next + else: + if self.oldest_item.next: + # old = old.next + item_to_remove = self.oldest_item + self.oldest_item = self.oldest_item.next + # remove old + if item_to_remove is self.storage.head: + new_node = Node(item) + new_node.next = self.storage.head.next + self.storage.head.next = None + self.storage.head = new_node + else: + node = self.storage.head + while node: + if node.next is item_to_remove: + new_node = Node(item) + new_node.next = self.oldest_item + if new_node is self.storage.head: + self.storage.head = new_node + else: + node.next = new_node + break + node = node.next + else: + # find item that .next is old + # reassign .next to new + node = self.storage.head + while node: + if node.next is self.oldest_item: + node.next = Node(item) + self.oldest_item = self.oldest_item + self.storage.length += 1 + break + node = node.next + + def get(self): + arr = [] + node = self.storage.head + while node: + arr.append(node.value) + node = node.next + return arr + +buffer = RingBuffer(3) + +print(buffer.get()) # should return [] + +buffer.append('a') +buffer.append('b') +buffer.append('c') + +print(buffer.get()) # should return ['a', 'b', 'c'] + +# 'd' overwrites the oldest value in the ring buffer, which is 'a' +buffer.append('d') + +print(buffer.get()) # should return ['d', 'b', 'c'] + +buffer.append('e') + +print(buffer.get()) # should return ['d', 'e', 'c'] - def append(self, item): - pass +buffer.append('f') - def get(self): - pass \ No newline at end of file +print(buffer.get()) # should return ['d', 'e', 'f'] \ No newline at end of file From 4d860406dc9dc79c34d76cbdf81ef8485cafc8ca Mon Sep 17 00:00:00 2001 From: Asher Kobin Date: Fri, 15 May 2020 14:09:17 -0400 Subject: [PATCH 2/4] reverse --- reverse/reverse.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/reverse/reverse.py b/reverse/reverse.py index 6116252d1..d8a0cafd1 100644 --- a/reverse/reverse.py +++ b/reverse/reverse.py @@ -39,4 +39,11 @@ def contains(self, value): return False def reverse_list(self, node, prev): - pass + prev = None + cur = self.head + while cur is not None: + next = cur.next_node + cur.next_node = prev + prev = cur + cur = next + self.head = prev From fe65c0e715fd89da2c1e65d4b12ba0c3fc8130ca Mon Sep 17 00:00:00 2001 From: Asher Kobin Date: Fri, 15 May 2020 14:44:53 -0400 Subject: [PATCH 3/4] fix bug in ring buffer --- ring_buffer/ring_buffer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ring_buffer/ring_buffer.py b/ring_buffer/ring_buffer.py index dea87e57d..740830310 100644 --- a/ring_buffer/ring_buffer.py +++ b/ring_buffer/ring_buffer.py @@ -103,8 +103,9 @@ def append(self, item): while node: if node.next is self.oldest_item: node.next = Node(item) - self.oldest_item = self.oldest_item - self.storage.length += 1 + self.oldest_item = self.storage.head # correct + #self.oldest_item = self.oldest_item # NOOP! + #self.storage.length += 1 # OOPSIES! break node = node.next From cf9e7788bf7004920f6de7315bb080e1842ea93a Mon Sep 17 00:00:00 2001 From: Asher Kobin Date: Fri, 15 May 2020 17:41:42 -0400 Subject: [PATCH 4/4] refactor ringbuffer --- ring_buffer/ring_buffer.py | 103 +++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/ring_buffer/ring_buffer.py b/ring_buffer/ring_buffer.py index 740830310..29f228a52 100644 --- a/ring_buffer/ring_buffer.py +++ b/ring_buffer/ring_buffer.py @@ -59,53 +59,54 @@ def __init__(self, capacity): self.oldest_item = None def append(self, item): - if len(self.storage) == 0: - self.oldest_item = Node(item) - self.storage.head = self.oldest_item - self.storage.length += 1 - elif self.capacity > len(self.storage): - new_node = Node(item) - node = self.storage.head - while node: - if node.next is None: - node.next = Node(item) - self.oldest_item = self.oldest_item - self.storage.length += 1 - break - node = node.next - else: - if self.oldest_item.next: - # old = old.next - item_to_remove = self.oldest_item - self.oldest_item = self.oldest_item.next - # remove old - if item_to_remove is self.storage.head: - new_node = Node(item) - new_node.next = self.storage.head.next - self.storage.head.next = None - self.storage.head = new_node - else: - node = self.storage.head - while node: - if node.next is item_to_remove: - new_node = Node(item) - new_node.next = self.oldest_item - if new_node is self.storage.head: - self.storage.head = new_node - else: - node.next = new_node - break - node = node.next + # if there is capacity, insert node (could have created LinkedList.insert) + if self.capacity > len(self.storage): + if not self.storage.head: + self.storage.head = Node(item) + self.oldest_item = self.storage.head + self.storage.length += 1 else: - # find item that .next is old - # reassign .next to new node = self.storage.head while node: - if node.next is self.oldest_item: + if node.next is None: node.next = Node(item) - self.oldest_item = self.storage.head # correct - #self.oldest_item = self.oldest_item # NOOP! - #self.storage.length += 1 # OOPSIES! + self.oldest_item = self.oldest_item + self.storage.length += 1 + break + node = node.next + # else, remove oldest node and put new node in it's place (i.e swap) + else: + # remove the oldest item + # if oldest_item is the head, replace it with new item + item_to_remove = self.oldest_item + if item_to_remove is self.storage.head: + self.oldest_item = self.storage.head.next + new_node = Node(item) + new_node.next = self.storage.head.next + self.storage.head.next = None + self.storage.head = new_node + # else if oldest_item is the tail, replace it with new item + elif self.oldest_item.next is None: + node = self.storage.head + while node: + if node.next is item_to_remove: + new_node = Node(item) + node.next = new_node + self.oldest_item = self.storage.head + break + node = node.next + # else + else: + self.oldest_item = self.oldest_item.next + node = self.storage.head + while node: + if node.next is item_to_remove: + new_node = Node(item) + new_node.next = self.oldest_item + if new_node is self.storage.head: + self.storage.head = new_node + else: + node.next = new_node break node = node.next @@ -117,7 +118,7 @@ def get(self): node = node.next return arr -buffer = RingBuffer(3) +buffer = RingBuffer(6) print(buffer.get()) # should return [] @@ -138,4 +139,16 @@ def get(self): buffer.append('f') -print(buffer.get()) # should return ['d', 'e', 'f'] \ No newline at end of file +print(buffer.get()) # should return ['d', 'e', 'f'] + +buffer.append('g') +buffer.append('h') +buffer.append('i') +buffer.append('j') +buffer.append('k') +buffer.append('l') +buffer.append('m') +buffer.append('n') +buffer.append('o') + +print(buffer.get()) # should return ['g', 'e', 'f'] \ No newline at end of file