From 89b999f5d13263ff4691d9ad4a8ed210b2500994 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Fri, 24 Dec 2021 15:18:29 -0600 Subject: [PATCH 01/30] answers for arrays practice probs --- data_structures/2_Arrays/my_arrays.py | 49 +++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 data_structures/2_Arrays/my_arrays.py diff --git a/data_structures/2_Arrays/my_arrays.py b/data_structures/2_Arrays/my_arrays.py new file mode 100644 index 0000000..fd280e5 --- /dev/null +++ b/data_structures/2_Arrays/my_arrays.py @@ -0,0 +1,49 @@ +# 1. expenses +print("\n##### 1. Expenses #####") +expense = [2200, 2350, 2600, 2130, 2190] +print(f"1) In Feb, you spent extra \"{expense[1]-expense[0]}\" \ +compare to Jan.") +print(f"2) Total expense in first quarter is \ +\"{expense[0]+expense[1]+expense[2]}\".") +print(f"3) Is there any month you spent exactly $2000?\n\ + Ans: {any([x for x in expense if x == 2000])}") + +expense.append(1980) +print(f"4) Now expense of June is added, it is \"{expense[5]}\"") + +print(f"5) The expense of April was {expense[3]}, but") +expense[3] = expense[3]-200 +print(f" she returned one item, which costs $200, \ +so it is updated to \"{expense[3]}\".") + + +# 2. marvel +print("\n##### 2. Marvel #####") +heros = ['spider man', 'thor', 'hulk', 'iron man', 'captain america'] +print(f"1) Length of the list is \"{len(heros)}\".") + +heros.append('black panther') +print(f"2) Added black panther at the end of the list: {heros}") + +heros.remove('black panther') +heros.insert(3, 'black panther') +print(f"3) After hulk, need black panther: {heros[:]}") + +heros[1:3] = ['doctor stange'] +print(f"4) Removed thor and hulk and added doctor strage: {heros[:]}") + +heros.sort() +print(f"5) Sort the list: {heros}") + +# 3. odd_even_numbers + +print("\n##### 3. Odd numbers list #####") + + +def odd_between_1_and_max(max): + return [i for i in range(1, max+1) if i % 2 == 1] + + +m = int(input()) +list = odd_between_1_and_max(m) +print(f"When m is {m}, list is {list}") From dfa108cfce470d90fa1355cef9d75fd4c01451e5 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Fri, 24 Dec 2021 15:55:03 -0600 Subject: [PATCH 02/30] make it cleaner --- data_structures/2_Arrays/my_arrays.py | 52 +++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 data_structures/2_Arrays/my_arrays.py diff --git a/data_structures/2_Arrays/my_arrays.py b/data_structures/2_Arrays/my_arrays.py new file mode 100644 index 0000000..0f2605a --- /dev/null +++ b/data_structures/2_Arrays/my_arrays.py @@ -0,0 +1,52 @@ +# 1. expenses +print("\n##### 1. Expenses #####") +expense = [2200, 2350, 2600, 2130, 2190] + +print(f"1) In Feb, you spent extra \"{expense[1]-expense[0]}\" \ +compare to Jan.") + +print(f"2) Total expense in first quarter is \ +\"{expense[0]+expense[1]+expense[2]}\".") + +print(f"3) Is there any month you spent exactly $2000?\n\ + Ans: {any([x for x in expense if x == 2000])}") + +expense.append(1980) +print(f"4) Now expense of June is added, it is \"{expense[5]}\"") + +print(f"5) The expense of April was {expense[3]}, but") +expense[3] = expense[3]-200 +print(f" she returned one item, which costs $200, \ +so it is updated to \"{expense[3]}\".") + + +# 2. marvel +print("\n##### 2. Marvel #####") +heros = ['spider man', 'thor', 'hulk', 'iron man', 'captain america'] + +print(f"1) Length of the list is \"{len(heros)}\".") + +heros.append('black panther') +print(f"2) Added black panther at the end of the list: {heros}") + +heros.remove('black panther') +heros.insert(3, 'black panther') +print(f"3) After hulk, need black panther: {heros[:]}") + +heros[1:3] = ['doctor stange'] +print(f"4) Removed thor and hulk and added doctor strage: {heros[:]}") + +heros.sort() +print(f"5) Sort the list: {heros}") + +# 3. odd_numbers +print("\n##### 3. Odd number list #####") + + +def odd_between_1_and_max(max): + return [i for i in range(1, max+1) if i % 2 == 1] + + +m = int(input("Type max number for your list: ")) +list = odd_between_1_and_max(m) +print(f"Your list is {list}") From 29e075248d37596fc3d2e01d56fe87ffa29251b6 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Sat, 25 Dec 2021 19:47:55 -0600 Subject: [PATCH 03/30] answers for linked_list practice probs --- data_structures/3_LinkedList/3_linked_list.py | 59 ++++++++++++++++--- 1 file changed, 50 insertions(+), 9 deletions(-) diff --git a/data_structures/3_LinkedList/3_linked_list.py b/data_structures/3_LinkedList/3_linked_list.py index a6d9466..f0e9b37 100644 --- a/data_structures/3_LinkedList/3_linked_list.py +++ b/data_structures/3_LinkedList/3_linked_list.py @@ -3,6 +3,7 @@ def __init__(self, data=None, next=None): self.data = data self.next = next + class LinkedList: def __init__(self): self.head = None @@ -15,6 +16,7 @@ def print(self): llstr = '' while itr: llstr += str(itr.data)+' --> ' if itr.next else str(itr.data) + # llstr += str(itr.data) + ' --> ' itr = itr.next print(llstr) @@ -22,7 +24,7 @@ def get_length(self): count = 0 itr = self.head while itr: - count+=1 + count += 1 itr = itr.next return count @@ -44,10 +46,10 @@ def insert_at_end(self, data): itr.next = Node(data, None) def insert_at(self, index, data): - if index<0 or index>self.get_length(): + if index < 0 or index > self.get_length(): raise Exception("Invalid Index") - if index==0: + if index == 0: self.insert_at_begining(data) return @@ -63,10 +65,10 @@ def insert_at(self, index, data): count += 1 def remove_at(self, index): - if index<0 or index>=self.get_length(): + if index < 0 or index >= self.get_length(): raise Exception("Invalid Index") - if index==0: + if index == 0: self.head = self.head.next return @@ -78,22 +80,61 @@ def remove_at(self, index): break itr = itr.next - count+=1 + count += 1 def insert_values(self, data_list): self.head = None for data in data_list: self.insert_at_end(data) + def insert_after_value(self, data_after, data_to_insert): + # Search for first occurance of data_after value in linked list + # Now insert data_to_insert after data_after node + itr = self.head + while itr: + if itr.data == data_after: + node = Node(data_to_insert, itr.next) + itr.next = node + break + itr = itr.next + + def remove_by_value(self, data): + # Remove first node that contains data + if self.head.data == data: + self.head = self.head.next # Can Node be None? + return + itr = self.head + while itr.next: + if itr.next.data == data: + itr.next = itr.next.next + break + itr = itr.next + if __name__ == '__main__': + ''' ll = LinkedList() - ll.insert_values(["banana","mango","grapes","orange"]) - ll.insert_at(1,"blueberry") + ll.insert_values(["banana", "mango", "grapes", "orange"]) + ll.insert_at(1, "blueberry") ll.remove_at(2) ll.print() - ll.insert_values([45,7,12,567,99]) + ll.insert_values([45, 7, 12, 567, 99]) ll.insert_at_end(67) ll.print() + ''' + ll = LinkedList() + ll.insert_values(["banana", "mango", "grapes", "orange"]) + ll.print() + ll.insert_after_value("mango", "apple") # insert apple after mango + ll.print() + ll.remove_by_value("orange") # remove orange from linked list + ll.print() + ll.remove_by_value("figs") + ll.print() + ll.remove_by_value("banana") + ll.remove_by_value("mango") + ll.remove_by_value("apple") + ll.remove_by_value("grapes") + ll.print() From 1759588cc2f8b9bcfd24063f3185077532298313 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Sun, 26 Dec 2021 14:35:28 -0600 Subject: [PATCH 04/30] make it cleaner --- data_structures/3_LinkedList/linked_list.py | 122 ++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 data_structures/3_LinkedList/linked_list.py diff --git a/data_structures/3_LinkedList/linked_list.py b/data_structures/3_LinkedList/linked_list.py new file mode 100644 index 0000000..12acdec --- /dev/null +++ b/data_structures/3_LinkedList/linked_list.py @@ -0,0 +1,122 @@ +class Node: + def __init__(self, data=None, next=None): + self.data = data + self.next = next + + +class LinkedList: + def __init__(self): + self.head = None + + def print(self): + if self.head is None: + print("Linked list is empty") + return + itr = self.head + llstr = '' + while itr: + llstr += str(itr.data)+' --> ' if itr.next else str(itr.data) + # llstr += str(itr.data) + ' --> ' + itr = itr.next + print(llstr) + + def get_length(self): + count = 0 + itr = self.head + while itr: + count += 1 + itr = itr.next + return count + + def insert_at_begining(self, data): + node = Node(data, self.head) + self.head = node + + def insert_at_end(self, data): + if self.head is None: + self.head = Node(data, None) + return + itr = self.head + while itr.next: + itr = itr.next + itr.next = Node(data, None) + + def insert_at(self, index, data): + if index < 0 or index > self.get_length(): + raise Exception("Invalid Index") + if index == 0: + self.insert_at_begining(data) + return + + count = 0 + itr = self.head + while itr: + if count == index - 1: + node = Node(data, itr.next) + itr.next = node + break + itr = itr.next + count += 1 + + def remove_at(self, index): + if index < 0 or index >= self.get_length(): + raise Exception("Invalid Index") + + if index == 0: + self.head = self.head.next + return + + count = 0 + itr = self.head + while itr: + if count == index - 1: + itr.next = itr.next.next + break + itr = itr.next + count += 1 + + def insert_values(self, data_list): + self.head = None + for data in data_list: + self.insert_at_end(data) + + def insert_after_value(self, data_after, data_to_insert): + # Search for first occurance of data_after value in linked list + # Now insert data_to_insert after data_after node + itr = self.head + while itr: + if itr.data == data_after: + node = Node(data_to_insert, itr.next) + itr.next = node + break + itr = itr.next + + def remove_by_value(self, data): + # Remove first node that contains data + if self.head.data == data: + self.head = self.head.next # Can Node be None? + return + itr = self.head + while itr.next: + if itr.next.data == data: + itr.next = itr.next.next + break + itr = itr.next + + +if __name__ == '__main__': + + ll = LinkedList() + ll.insert_values(["banana", "mango", "grapes", "orange"]) + ll.print() + ll.insert_after_value("mango", "apple") # insert apple after mango + ll.print() + ll.remove_by_value("orange") # remove orange from linked list + ll.print() + ll.remove_by_value("figs") + ll.print() + ll.remove_by_value("banana") + ll.remove_by_value("mango") + ll.remove_by_value("apple") + ll.remove_by_value("grapes") + ll.print() From f81b1fa1624b5568f05a7704e93ea519cb6cec64 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Sun, 26 Dec 2021 15:22:58 -0600 Subject: [PATCH 05/30] rename the file --- data_structures/3_LinkedList/3_linked_list.py | 140 ------------------ 1 file changed, 140 deletions(-) delete mode 100644 data_structures/3_LinkedList/3_linked_list.py diff --git a/data_structures/3_LinkedList/3_linked_list.py b/data_structures/3_LinkedList/3_linked_list.py deleted file mode 100644 index f0e9b37..0000000 --- a/data_structures/3_LinkedList/3_linked_list.py +++ /dev/null @@ -1,140 +0,0 @@ -class Node: - def __init__(self, data=None, next=None): - self.data = data - self.next = next - - -class LinkedList: - def __init__(self): - self.head = None - - def print(self): - if self.head is None: - print("Linked list is empty") - return - itr = self.head - llstr = '' - while itr: - llstr += str(itr.data)+' --> ' if itr.next else str(itr.data) - # llstr += str(itr.data) + ' --> ' - itr = itr.next - print(llstr) - - def get_length(self): - count = 0 - itr = self.head - while itr: - count += 1 - itr = itr.next - - return count - - def insert_at_begining(self, data): - node = Node(data, self.head) - self.head = node - - def insert_at_end(self, data): - if self.head is None: - self.head = Node(data, None) - return - - itr = self.head - - while itr.next: - itr = itr.next - - itr.next = Node(data, None) - - def insert_at(self, index, data): - if index < 0 or index > self.get_length(): - raise Exception("Invalid Index") - - if index == 0: - self.insert_at_begining(data) - return - - count = 0 - itr = self.head - while itr: - if count == index - 1: - node = Node(data, itr.next) - itr.next = node - break - - itr = itr.next - count += 1 - - def remove_at(self, index): - if index < 0 or index >= self.get_length(): - raise Exception("Invalid Index") - - if index == 0: - self.head = self.head.next - return - - count = 0 - itr = self.head - while itr: - if count == index - 1: - itr.next = itr.next.next - break - - itr = itr.next - count += 1 - - def insert_values(self, data_list): - self.head = None - for data in data_list: - self.insert_at_end(data) - - def insert_after_value(self, data_after, data_to_insert): - # Search for first occurance of data_after value in linked list - # Now insert data_to_insert after data_after node - itr = self.head - while itr: - if itr.data == data_after: - node = Node(data_to_insert, itr.next) - itr.next = node - break - itr = itr.next - - def remove_by_value(self, data): - # Remove first node that contains data - if self.head.data == data: - self.head = self.head.next # Can Node be None? - return - itr = self.head - while itr.next: - if itr.next.data == data: - itr.next = itr.next.next - break - itr = itr.next - - -if __name__ == '__main__': - ''' - ll = LinkedList() - ll.insert_values(["banana", "mango", "grapes", "orange"]) - ll.insert_at(1, "blueberry") - ll.remove_at(2) - ll.print() - - ll.insert_values([45, 7, 12, 567, 99]) - ll.insert_at_end(67) - ll.print() - ''' - - ll = LinkedList() - ll.insert_values(["banana", "mango", "grapes", "orange"]) - ll.print() - ll.insert_after_value("mango", "apple") # insert apple after mango - ll.print() - ll.remove_by_value("orange") # remove orange from linked list - ll.print() - ll.remove_by_value("figs") - ll.print() - ll.remove_by_value("banana") - ll.remove_by_value("mango") - ll.remove_by_value("apple") - ll.remove_by_value("grapes") - ll.print() From e3c78408ebadcb57e676ea9f9fd965a4ff9964bd Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Sun, 26 Dec 2021 15:23:28 -0600 Subject: [PATCH 06/30] answers for double_linked_list practice probs --- .../3_LinkedList/double_linked_list.py | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 data_structures/3_LinkedList/double_linked_list.py diff --git a/data_structures/3_LinkedList/double_linked_list.py b/data_structures/3_LinkedList/double_linked_list.py new file mode 100644 index 0000000..b3df789 --- /dev/null +++ b/data_structures/3_LinkedList/double_linked_list.py @@ -0,0 +1,161 @@ +class Node: + def __init__(self, data=None, next=None, prev=None): + self.data = data + self.next = next + self.prev = prev + + +class DoubleLinkedList: + def __init__(self): + self.head = None + self.tail = None + + def isHead(self, node): + return(node == self.head) + + def isTail(self, node): + return(node == self.tail) + + def print_forward(self): + # This method prints list in forward direction. Use node.next + if self.head is None: + print("Double linked list is empty") + return + itr = self.head + llstr = '' + while itr: + llstr += str(itr.data) + ' --> ' if itr.next else str(itr.data) + itr = itr.next + print(llstr) + + def print_backward(self): + # Print linked list in reverse direction. Use node.prev for this. + if self.tail is None: + print("Double linked list is empty") + return + itr = self.tail + llstr = '' + while itr: + llstr += str(itr.data) + ' <-- ' if itr.prev else str(itr.data) + itr = itr.prev + print(llstr) + + def get_length(self): + count = 0 + itr = self.head + while itr: + count += 1 + itr = itr.next + return count + + def insert_at_beginning(self, data): + if self.get_length() == 0: + node = Node(data) + self.head = node + self.tail = node + else: + old_head = self.head + node = Node(data, old_head) + self.head = node + old_head.prev = node + + def insert_at_end(self, data): + if self.get_length() == 0: + self.insert_at_beginning(data) + else: + old_tail = self.tail + node = Node(data, None, old_tail) + self.tail = node + old_tail.next = node + + def insert_at(self, index, data): + if index < 0 or index >= self.get_length(): + raise Exception("Invalid Index") + if index == 0: + self.insert_at_beginning(data) + itr = self.head + count = 0 + while itr: + if count == index - 1: + next_node = itr.next + node = Node(data, next_node, itr) + itr.next = node + next_node.prev = node + break + count += 1 + itr = itr.next + + def remove_at(self, index): + # index doesn't match + if index < 0 or index >= self.get_length(): + raise Exception("Invalid Index") + # remove head + if index == 0: + if self.isTail(self.head): + self.tail = None + self.head = None + else: + self.head = self.head.next + self.head.prev = None + return + # remove head + if index == self.get_length() - 1: + self.tail = self.tail.prev + self.tail.next = None + return + # other cases + itr = self.head + count = 0 + while itr.next: + if count == index - 1: + if self.isTail(itr.next): + itr.next.next = None + else: + itr.next.next.prev = itr + itr.next = itr.next.next + break + itr = itr.next + count += 1 + + def insert_values(self, data_list): + self.head = None + self.tail = None + for data in data_list: + self.insert_at_end(data) + + def insert_after_value(self, data_after, data_to_insert): + itr = self.head + while itr: + if itr.data == data_after: + node = Node(data_to_insert, itr.next, itr) + itr.next.prev = node + itr.next = node + break + itr = itr.next + + def remove_by_value(self, data): + itr = self.head + while itr: + if itr.data == data: + if self.isHead(itr): + if self.isTail(itr): + self.head = None + self.tail = None + else: + self.head = itr.next + self.head.prev = None + elif self.isTail(itr): + self.tail = self.tail.prev + self.tail.next = None + else: + itr.prev.next = itr.next + itr.next.prev = itr.prev + break + itr = itr.next + + +if __name__ == '__main__': + ll = DoubleLinkedList() + ll.insert_values([45, 7, 12, 567, 99]) + ll.remove_by_value(99) + ll.print_forward() From d953fc661ab01b416338a100b79e0784408b6150 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 27 Dec 2021 13:07:31 -0600 Subject: [PATCH 07/30] fix errors with tail --- .../3_LinkedList/double_linked_list.py | 76 +++++++++++++++---- 1 file changed, 60 insertions(+), 16 deletions(-) diff --git a/data_structures/3_LinkedList/double_linked_list.py b/data_structures/3_LinkedList/double_linked_list.py index b3df789..b0ac9d9 100644 --- a/data_structures/3_LinkedList/double_linked_list.py +++ b/data_structures/3_LinkedList/double_linked_list.py @@ -9,6 +9,9 @@ class DoubleLinkedList: def __init__(self): self.head = None self.tail = None + # not having tail pointer would function similarly + # but only appending item to the list is O(n) + # because you have to traverse the whole list to get to the end def isHead(self, node): return(node == self.head) @@ -28,6 +31,21 @@ def print_forward(self): itr = itr.next print(llstr) + def print_with_info(self): + if self.head is None: + print("Double linked list is empty") + return + itr = self.head + llstr = '' + while itr: + if self.isHead(itr): + llstr += '(head) ' + if self.isTail(itr): + llstr += '(tail) ' + llstr += str(itr.data) + ' --> ' if itr.next else str(itr.data) + itr = itr.next + print(llstr) + def print_backward(self): # Print linked list in reverse direction. Use node.prev for this. if self.tail is None: @@ -49,45 +67,50 @@ def get_length(self): return count def insert_at_beginning(self, data): - if self.get_length() == 0: + if self.get_length() == 0: # Same as self.head == None node = Node(data) self.head = node self.tail = node else: - old_head = self.head - node = Node(data, old_head) + node = Node(data, self.head) + self.head.prev = node self.head = node - old_head.prev = node def insert_at_end(self, data): - if self.get_length() == 0: + if self.get_length() == 0: # Same as self.head == None self.insert_at_beginning(data) else: - old_tail = self.tail - node = Node(data, None, old_tail) + node = Node(data, None, self.tail) + self.tail.next = node self.tail = node - old_tail.next = node def insert_at(self, index, data): - if index < 0 or index >= self.get_length(): + # index doesn't match + if index < 0 or index > self.get_length(): raise Exception("Invalid Index") + # insert at head if index == 0: self.insert_at_beginning(data) + return + # other cases itr = self.head count = 0 while itr: if count == index - 1: - next_node = itr.next - node = Node(data, next_node, itr) + node = Node(data, itr.next, itr) + if itr.next: + itr.next.prev = node + if self.isTail(itr): + self.tail = node itr.next = node - next_node.prev = node break - count += 1 itr = itr.next + count += 1 def remove_at(self, index): + len = self.get_length() # index doesn't match - if index < 0 or index >= self.get_length(): + if index < 0 or index >= len: raise Exception("Invalid Index") # remove head if index == 0: @@ -98,8 +121,8 @@ def remove_at(self, index): self.head = self.head.next self.head.prev = None return - # remove head - if index == self.get_length() - 1: + # remove tail + if index == len - 1: self.tail = self.tail.prev self.tail.next = None return @@ -155,7 +178,28 @@ def remove_by_value(self, data): if __name__ == '__main__': + ''' ll = DoubleLinkedList() ll.insert_values([45, 7, 12, 567, 99]) ll.remove_by_value(99) ll.print_forward() + ''' + ll = DoubleLinkedList() + ll.insert_values(["banana", "mango", "grapes", "orange"]) + ll.print_forward() + ll.print_backward() + ll.insert_at_end("figs") + ll.print_with_info() + ll.insert_at(0, "jackfruit") + ll.print_with_info() + ll.insert_at(6, "dates") # this is where tail got messed up + ll.print_with_info() + ll.insert_at(2, "kiwi") + ll.print_with_info() + print("--------------------------") + ll.remove_at(0) + ll.print_with_info() + ll.remove_at(ll.get_length()-1) + ll.print_with_info() + ll.remove_at(3) + ll.print_with_info() From d38fc150f507c2c2c7e4ee97080bc9e43d23a831 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 27 Dec 2021 13:08:02 -0600 Subject: [PATCH 08/30] checking the correct answer --- .../Solution/doubly_linked_list_exercise.py | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/data_structures/3_LinkedList/Solution/doubly_linked_list_exercise.py b/data_structures/3_LinkedList/Solution/doubly_linked_list_exercise.py index 35b9c38..b482e85 100644 --- a/data_structures/3_LinkedList/Solution/doubly_linked_list_exercise.py +++ b/data_structures/3_LinkedList/Solution/doubly_linked_list_exercise.py @@ -4,6 +4,7 @@ def __init__(self, data=None, next=None, prev=None): self.next = next self.prev = prev + class DoublyLinkedList: def __init__(self): self.head = None @@ -44,7 +45,7 @@ def get_length(self): count = 0 itr = self.head while itr: - count+=1 + count += 1 itr = itr.next return count @@ -71,10 +72,10 @@ def insert_at_end(self, data): itr.next = Node(data, None, itr) def insert_at(self, index, data): - if index<0 or index>self.get_length(): + if index < 0 or index > self.get_length(): raise Exception("Invalid Index") - if index==0: + if index == 0: self.insert_at_begining(data) return @@ -92,10 +93,10 @@ def insert_at(self, index, data): count += 1 def remove_at(self, index): - if index<0 or index>=self.get_length(): + if index < 0 or index >= self.get_length(): raise Exception("Invalid Index") - if index==0: + if index == 0: self.head = self.head.next self.head.prev = None return @@ -110,7 +111,7 @@ def remove_at(self, index): break itr = itr.next - count+=1 + count += 1 def insert_values(self, data_list): self.head = None @@ -120,16 +121,21 @@ def insert_values(self, data_list): if __name__ == '__main__': ll = DoublyLinkedList() - ll.insert_values(["banana","mango","grapes","orange"]) + ll.insert_values(["banana", "mango", "grapes", "orange"]) ll.print_forward() ll.print_backward() ll.insert_at_end("figs") ll.print_forward() - ll.insert_at(0,"jackfruit") + ll.insert_at(0, "jackfruit") ll.print_forward() - ll.insert_at(6,"dates") + ll.insert_at(6, "dates") ll.print_forward() - ll.insert_at(2,"kiwi") + ll.insert_at(2, "kiwi") + ll.print_forward() + print("--------------------------") + ll.remove_at(0) + ll.print_forward() + ll.remove_at(ll.get_length()-1) + ll.print_forward() + ll.remove_at(3) ll.print_forward() - - From afc3980bf0a21cec231e955f64e066067aca64fb Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 27 Dec 2021 14:40:29 -0600 Subject: [PATCH 09/30] difference between using list and array for search and basic implementation of hash table --- data_structures/4_HashTable/hash_table.py | 79 +++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 data_structures/4_HashTable/hash_table.py diff --git a/data_structures/4_HashTable/hash_table.py b/data_structures/4_HashTable/hash_table.py new file mode 100644 index 0000000..669cecf --- /dev/null +++ b/data_structures/4_HashTable/hash_table.py @@ -0,0 +1,79 @@ +# [ array ] +import os +stock_price_list = [] +abs_path = os.path.dirname(os.path.abspath(__file__)) +file_name = abs_path + '/stock_prices.csv' +with open(file_name, "r") as f: + for line in f: + tokens = line.split(',') + day = tokens[0] + price = float(tokens[1]) + stock_price_list.append([day, price]) + +print(stock_price_list) +# to find stock price on march 9 +for element in stock_price_list: + if element[0] == 'march 9': + print(element[1]) +# --> complexity of search using a list is O(n) + + +# [ dictionary (hashmap) ] +stock_price_dict = {} +with open(file_name, "r") as f: + for line in f: + tokens = line.split(',') + stock_price_dict[tokens[0]] = float(tokens[1]) + +print(stock_price_dict) +# to find stock price on march 9 +stock_price_dict['march 9'] +# --> complexity of search using a dictionaty is O(1) + + +# [ Implement Hash Table ] + +# hash function converts your string key into an index into array +# hash functions 1) using ASCII numbers +# --> add all ASCII numbers of string key and +# reduce number using mod (to get indexes less than array size) +# (e.g. if array size is 10, mod(609, 10) -> 9 + +# ord() returns an integer representing the Unicode character +# ASCII encoding : ascii value to binary (Western characters) +# each character becomes 8bits/1byte of binary data +# there are also Unicode encodings ... + +class HashTable: + def __init__(self): + self.MAX = 100 + self.arr = [None for i in range(self.MAX)] + + def get_hash(self, key): + hash = 0 + for char in key: + hash += ord(char) + return hash % self.MAX + + def __getitem__(self, index): + h = self.get_hash(index) + return self.arr[h] + + def __setitem__(self, key, val): + h = self.get_hash(key) + self.arr[h] = val + + def __delitem__(self, key): + h = self.get_hash(key) + self.arr[h] = None + + +t = HashTable() +t["march 6"] = 310 +print(t["march 6"]) +print(t["march 10"]) +del t["march 6"] +print(t["march 6"]) + +# lookup by key: O(1) on average +# insertion/deletion: O(1) on average From a6e29a62f3332cf975da25c8f60502aa642e0cda Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 27 Dec 2021 22:02:26 -0600 Subject: [PATCH 10/30] answers for hash_table practice probs --- .../4_HashTable_2_Collisions/hash_table.py | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 data_structures/4_HashTable_2_Collisions/hash_table.py diff --git a/data_structures/4_HashTable_2_Collisions/hash_table.py b/data_structures/4_HashTable_2_Collisions/hash_table.py new file mode 100644 index 0000000..2aa209a --- /dev/null +++ b/data_structures/4_HashTable_2_Collisions/hash_table.py @@ -0,0 +1,214 @@ +# Exercise: Hash Table + +''' +1. [nyc_weather.csv](https://github.com/codebasics/data-structures-algorithms-python/blob/master/data_structures/4_HashTable_2_Collisions/Solution/nyc_weather.csv) + contains new york city weather for first few days in the month of January. + Write a program that can answer following, + 1. What was the average temperature in first week of Jan + 2. What was the maximum temperature in first 10 days of Jan + +Figure out data structure that is best for this problem +''' +import os +temp_list = [] +abs_path = os.path.dirname(os.path.abspath(__file__)) +temp_file = abs_path + '/Solution/nyc_weather.csv' +with open(temp_file, "r") as f: + for line in f: + tokens = line.split(',') + if tokens[0] == 'date': + pass + else: + temp_list.append(int(tokens[1])) +print("\nExercise Problem 1)") +print(f"Best data structure: List\n{temp_list}") +print(f"The avaerage temperature in first week of Jan: \ +{round(sum(temp_list[:7])/7,2)}") +print(f"The maximum temperature in first 10 days of Jan: {max(temp_list)}") + + +''' +2. [nyc_weather.csv](https://github.com/codebasics/data-structures-algorithms-python/blob/master/data_structures/4_HashTable_2_Collisions/Solution/nyc_weather.csv) + contains new york city weather for first few days in the month of January. + Write a program that can answer following, + 1. What was the temperature on Jan 9? + 2. What was the temperature on Jan 4? + +Figure out data structure that is best for this problem +''' +temp_dict = {} +with open(temp_file, "r") as f: + for line in f: + tokens = line.split(',') + if tokens[0] == 'date': + pass + else: + temp_dict[tokens[0]] = int(tokens[1]) +print("\nExercise Problem 2)") +print(f"Best data structure: Dictionary\n{temp_dict}") +print(f"The temperature on Jan 9: {temp_dict['Jan 9']}") +print(f"The temperature on Jan 4: {temp_dict['Jan 4']}") + + +''' +3. [poem.txt](https://github.com/codebasics/data-structures-algorithms-python/blob/master/data_structures/4_HashTable_2_Collisions/Solution/poem.txt) + contains famous poem "Road not taken" by poet Robert Frost. + You have to read this file in python and print every word and its count as show below. + Think about the best data structure that you can use to solve this problem + and figure out why you selected that specific data structure. + + 'diverged': 2, + 'in': 3, + 'I': 8 +''' +word_dict = {} +poem_file = abs_path + '/Solution/poem.txt' +with open(poem_file, "r") as f: + for line in f: + for word in line.split(): + key = word.strip('—.;,\n') + if key in word_dict: + word_dict[key] += 1 + else: + word_dict[key] = 1 +print("\nExercise Problem 3)") +print(f"Best data structure: Dictionary\n{word_dict}") + + +''' +4. Implement hash table where collisions are handled using linear probing. + We learnt about linear probing in the video tutorial. + Take the hash table implementation that uses chaining and modify methods to use **linear probing**. + Keep MAX size of arr in hashtable as 10. +''' + + +class HashTable: + def __init__(self): + self.MAX = 10 + self.arr = [(None, None) for i in range(self.MAX)] + + def get_hash(self, key): + hash = 0 + for char in key: + hash += ord(char) + return hash % self.MAX + + def __getitem__(self, key): + arr_index = self.get_hash(key) + if self.arr[arr_index][0] == key: + return self.arr[arr_index][1] + else: + found = False + if arr_index + 1 == self.MAX: + idx = 0 + else: + idx = arr_index + 1 + while (not found and idx != arr_index): + if self.arr[idx][0] == key: + found = True + return self.arr[idx][1] + else: + if idx + 1 == self.MAX: + idx = 0 + else: + idx += 1 + + def __setitem__(self, key, val): + h = self.get_hash(key) + if self.arr[h][0] in (key, None): + self.arr[h] = (key, val) + else: + if h + 1 == self.MAX: + idx = 0 + else: + idx = h + 1 + new_idx = None + found = False + while not found and idx != h: + target = self.arr[idx][0] + if target == key: + found = True + self.arr[idx] = (key, val) + else: + if target == None and new_idx == None: + new_idx = idx + if idx + 1 == self.MAX: + idx = 0 + else: + idx += 1 + if not found: + if new_idx == None: + raise Exception("Hashmap is full") + else: + self.arr[new_idx] = (key, val) + + # Problem) deleted position should have (None, None) but + # it just deletes the one entry + def __delitem__(self, key): + arr_index = self.get_hash(key) + if self.arr[arr_index][0] == key: + del self.arr[arr_index] + else: + found = False + if arr_index + 1 == self.MAX: + idx = 0 + else: + idx = arr_index + 1 + while (not found and idx != arr_index): + if self.arr[idx][0] == key: + found = True + self.arr[idx] = (None, None) + else: + if idx + 1 == self.MAX: + idx = 0 + else: + idx += 1 + + +print("\nExercise Problem 4)") +''' +t = HashTable() +t["march 6"] = 310 +t["march 7"] = 420 +t["march 8"] = 67 +t["march 17"] = 63457 +print(t["march 6"]) +print(t["march 17"]) +print(t.arr) +t["march 6"] = 11 +print(t["march 6"]) +print(t.arr) + +del t["march 7"] +print(t.arr) +''' +t = HashTable() +t["march 6"] = 20 +t["march 17"] = 88 +print(t.arr) +t["march 17"] = 29 +print(t.arr) +t["nov 1"] = 1 +print(t.arr) +t["march 33"] = 234 +print(t.arr) +print(t["dec 1"]) +print(t["march 33"]) +t["march 33"] = 999 +print(t.arr) +t["april 1"] = 87 +print(t.arr) +t["april 2"] = 123 +print(t.arr) +t["april 3"] = 234234 +print(t.arr) +t["april 4"] = 91 +print(t.arr) +t["May 22"] = 4 +print(t.arr) +t["May 7"] = 47 +print(t.arr) +# t["Jan 1"] = 0 --> raise exception +del t["april 2"] +print(t.arr) From d76554516e2dea8dffee07d4d29a1ca48b337579 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 27 Dec 2021 22:02:57 -0600 Subject: [PATCH 11/30] edited for testing --- .../4_hash_table_collision_handling.ipynb | 71 ++++++++++++------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/data_structures/4_HashTable_2_Collisions/4_hash_table_collision_handling.ipynb b/data_structures/4_HashTable_2_Collisions/4_hash_table_collision_handling.ipynb index 0cebc4e..1547a47 100644 --- a/data_structures/4_HashTable_2_Collisions/4_hash_table_collision_handling.ipynb +++ b/data_structures/4_HashTable_2_Collisions/4_hash_table_collision_handling.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 56, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ @@ -28,7 +28,7 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -37,7 +37,7 @@ "9" ] }, - "execution_count": 51, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -49,7 +49,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 22, "metadata": { "scrolled": false }, @@ -60,7 +60,7 @@ "9" ] }, - "execution_count": 12, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" } @@ -71,7 +71,7 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 23, "metadata": {}, "outputs": [], "source": [ @@ -83,7 +83,7 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -92,7 +92,7 @@ "459" ] }, - "execution_count": 55, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -110,7 +110,7 @@ }, { "cell_type": "code", - "execution_count": 86, + "execution_count": 25, "metadata": {}, "outputs": [], "source": [ @@ -152,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": 87, + "execution_count": 26, "metadata": {}, "outputs": [], "source": [ @@ -165,7 +165,7 @@ }, { "cell_type": "code", - "execution_count": 88, + "execution_count": 27, "metadata": { "scrolled": true }, @@ -176,7 +176,7 @@ "310" ] }, - "execution_count": 88, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } @@ -187,7 +187,7 @@ }, { "cell_type": "code", - "execution_count": 89, + "execution_count": 28, "metadata": { "scrolled": true }, @@ -198,7 +198,7 @@ "63457" ] }, - "execution_count": 89, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -209,7 +209,7 @@ }, { "cell_type": "code", - "execution_count": 90, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -227,7 +227,7 @@ " [('march 6', 310), ('march 17', 63457)]]" ] }, - "execution_count": 90, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -238,7 +238,7 @@ }, { "cell_type": "code", - "execution_count": 91, + "execution_count": 30, "metadata": { "scrolled": true }, @@ -249,7 +249,7 @@ }, { "cell_type": "code", - "execution_count": 92, + "execution_count": 31, "metadata": {}, "outputs": [ { @@ -267,7 +267,7 @@ " [('march 6', 11), ('march 17', 63457)]]" ] }, - "execution_count": 92, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -278,16 +278,16 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "310" + "11" ] }, - "execution_count": 68, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } @@ -298,7 +298,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 36, "metadata": {}, "outputs": [ { @@ -310,7 +310,28 @@ } ], "source": [ - "del t[\"march 6\"]" + "del t[\"march 6\"]\n", + "del t[\"march 17\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[('march 7', 420)], [('march 8', 67)], [], [], [], [], [], [], [], []]" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "t.arr" ] } ], @@ -330,7 +351,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.9.5" } }, "nbformat": 4, From 6334b51d447c189ec23f991119662201d54c7f6b Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 27 Dec 2021 22:17:36 -0600 Subject: [PATCH 12/30] Added the lesson learned after looking at the solution --- .../4_HashTable_2_Collisions/hash_table.py | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/data_structures/4_HashTable_2_Collisions/hash_table.py b/data_structures/4_HashTable_2_Collisions/hash_table.py index 2aa209a..818938d 100644 --- a/data_structures/4_HashTable_2_Collisions/hash_table.py +++ b/data_structures/4_HashTable_2_Collisions/hash_table.py @@ -21,7 +21,8 @@ else: temp_list.append(int(tokens[1])) print("\nExercise Problem 1)") -print(f"Best data structure: List\n{temp_list}") +print(f"The best data structure to use here was a list\n\ +because all we wanted was access of temperature elements") print(f"The avaerage temperature in first week of Jan: \ {round(sum(temp_list[:7])/7,2)}") print(f"The maximum temperature in first 10 days of Jan: {max(temp_list)}") @@ -45,7 +46,9 @@ else: temp_dict[tokens[0]] = int(tokens[1]) print("\nExercise Problem 2)") -print(f"Best data structure: Dictionary\n{temp_dict}") +print(f"The best data structure to use here was a dictionary (internally a hash table)\n\ +because we wanted to know temperature for specific day, requiring key, value pair access\n\ +where you can look up an element by day using O(1) complexity") print(f"The temperature on Jan 9: {temp_dict['Jan 9']}") print(f"The temperature on Jan 4: {temp_dict['Jan 4']}") @@ -167,21 +170,10 @@ def __delitem__(self, key): print("\nExercise Problem 4)") -''' -t = HashTable() -t["march 6"] = 310 -t["march 7"] = 420 -t["march 8"] = 67 -t["march 17"] = 63457 -print(t["march 6"]) -print(t["march 17"]) -print(t.arr) -t["march 6"] = 11 -print(t["march 6"]) -print(t.arr) - -del t["march 7"] -print(t.arr) +print(f"Tested fine.\n\ +Even took care of the corner case that the solution didn't take care of,\n\ +which is get or set item that has been stored at somewhere else when the arr[h] gets deleted.\n\ +Lesson learned: use helper fuction!!!! (the current code is too hard to read)") ''' t = HashTable() t["march 6"] = 20 @@ -212,3 +204,4 @@ def __delitem__(self, key): # t["Jan 1"] = 0 --> raise exception del t["april 2"] print(t.arr) +''' From fa9f807058078064d2ce825ce1cd88adc71d5348 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 27 Dec 2021 22:39:24 -0600 Subject: [PATCH 13/30] added info of practice probs --- data_structures/5_Stack/stack.py | 21 +++++++++ data_structures/6_Queue/queue.py | 45 +++++++++++++++++++ data_structures/7_Tree/tree.py | 1 + .../8_Binary_Tree_1/binary_tree_part_1.py | 25 ++++++++--- 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 data_structures/5_Stack/stack.py create mode 100644 data_structures/6_Queue/queue.py create mode 100644 data_structures/7_Tree/tree.py diff --git a/data_structures/5_Stack/stack.py b/data_structures/5_Stack/stack.py new file mode 100644 index 0000000..86a71df --- /dev/null +++ b/data_structures/5_Stack/stack.py @@ -0,0 +1,21 @@ +# Exercise: Stack + +''' +1. Write a function in python that can reverse a string using stack data structure. + Use `5_stack.ipynb` from the tutorial. + + reverse_string("We will conquere COVID-19") should return "91-DIVOC ereuqnoc lliw eW" +''' + +''' +2. Write a function in python that checks if paranthesis in the string are balanced or not. + Possible parantheses are "{}',"()" or "[]". + Use `5_stack.ipynb` from the tutorial. + + is_balanced("({a+b})") --> True + is_balanced("))((a+b}{") --> False + is_balanced("((a+b))") --> True + is_balanced("))") --> False + is_balanced("[a+b]*(x+2y)*{gg+kk}") --> True + +''' diff --git a/data_structures/6_Queue/queue.py b/data_structures/6_Queue/queue.py new file mode 100644 index 0000000..6d9311a --- /dev/null +++ b/data_structures/6_Queue/queue.py @@ -0,0 +1,45 @@ +# Data structure tutorial exercise: Queue + +''' +1. Design a food ordering system where your python program will run two threads, + 1. Place Order: This thread will be placing an order and inserting that into a queue. + This thread places new order every 0.5 second. (hint: use time.sleep(0.5) function) + 2. Serve Order: This thread will server the order. + All you need to do is pop the order out of the queue and print it. + This thread serves an order every 2 seconds. + Also start this thread 1 second after place order thread is started. + + Use this video to get yourself familiar with [multithreading in python + (https://www.youtube.com/watch?v=PJ4t2U15ACo&list=PLeo1K3hjS3uub3PRhdoCTY8BxMKSW7RjN&index=2&t=0s) + + Pass following list as an argument to place order thread, + + orders = ['pizza','samosa','pasta','biryani','burger'] + + This problem is a producer,consumer problem + where place_order thread is producing orders whereas server_order thread is consuming the food orders. + Use Queue class implemented in a video tutorial. +''' + +''' +2. Write a program to print binary numbers from 1 to 10 using Queue. +Use Queue class implemented in main tutorial. +Binary sequence should look like, + + 1 + 10 + 11 + 100 + 101 + 110 + 111 + 1000 + 1001 + 1010 + +Hint: Notice a pattern above. +After 1 second and third number is 1+0 and 1+1. +4th and 5th number are second number (i.e. 10) + 0 and second number (i.e. 10) + 1. + +You also need to add front() function in queue class that can return the front element in the queue. +''' diff --git a/data_structures/7_Tree/tree.py b/data_structures/7_Tree/tree.py new file mode 100644 index 0000000..584cc28 --- /dev/null +++ b/data_structures/7_Tree/tree.py @@ -0,0 +1 @@ +# Data structure tutorial exercise: General Tree diff --git a/data_structures/8_Binary_Tree_1/binary_tree_part_1.py b/data_structures/8_Binary_Tree_1/binary_tree_part_1.py index 2c453a7..f162761 100644 --- a/data_structures/8_Binary_Tree_1/binary_tree_part_1.py +++ b/data_structures/8_Binary_Tree_1/binary_tree_part_1.py @@ -6,7 +6,7 @@ def __init__(self, data): def add_child(self, data): if data == self.data: - return # node already exist + return # node already exist if data < self.data: if self.left: @@ -19,7 +19,6 @@ def add_child(self, data): else: self.right = BinarySearchTreeNode(data) - def search(self, val): if self.data == val: return True @@ -50,20 +49,34 @@ def in_order_traversal(self): def build_tree(elements): - print("Building tree with these elements:",elements) + print("Building tree with these elements:", elements) root = BinarySearchTreeNode(elements[0]) - for i in range(1,len(elements)): + for i in range(1, len(elements)): root.add_child(elements[i]) return root + +''' +Add following methods to [BinarySearchTreeNode class](https://github.com/codebasics/data-structures-algorithms-python/blob/master/data_structures/8_Binary_Tree_1/binary_tree_part_1.py) created in main video tutorial + + 1. find_min(): finds minimum element in entire binary tree + 2. find_max(): finds maximum element in entire binary tree + 3. calculate_sum(): calcualtes sum of all elements + 4. post_order_traversal(): performs post order traversal of a binary tree + 5. pre_order_traversal(): perofrms pre order traversal of a binary tree +''' + + if __name__ == '__main__': - countries = ["India","Pakistan","Germany", "USA","China","India","UK","USA"] + countries = ["India", "Pakistan", "Germany", + "USA", "China", "India", "UK", "USA"] country_tree = build_tree(countries) print("UK is in the list? ", country_tree.search("UK")) print("Sweden is in the list? ", country_tree.search("Sweden")) numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) - print("In order traversal gives this sorted list:",numbers_tree.in_order_traversal()) \ No newline at end of file + print("In order traversal gives this sorted list:", + numbers_tree.in_order_traversal()) From 065da3996cff00b25535b0ff03af8e78abf0ae52 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Tue, 28 Dec 2021 16:40:56 -0600 Subject: [PATCH 14/30] renamed the file --- data_structures/2_Arrays/{my_arrays.py => arrays.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename data_structures/2_Arrays/{my_arrays.py => arrays.py} (100%) diff --git a/data_structures/2_Arrays/my_arrays.py b/data_structures/2_Arrays/arrays.py similarity index 100% rename from data_structures/2_Arrays/my_arrays.py rename to data_structures/2_Arrays/arrays.py From 17092c4f00c69b85a31306ad703744a2830028ab Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Tue, 28 Dec 2021 16:41:14 -0600 Subject: [PATCH 15/30] added main method --- data_structures/4_HashTable/hash_table.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/data_structures/4_HashTable/hash_table.py b/data_structures/4_HashTable/hash_table.py index 669cecf..2d05fa7 100644 --- a/data_structures/4_HashTable/hash_table.py +++ b/data_structures/4_HashTable/hash_table.py @@ -68,12 +68,13 @@ def __delitem__(self, key): self.arr[h] = None -t = HashTable() -t["march 6"] = 310 -print(t["march 6"]) -print(t["march 10"]) -del t["march 6"] -print(t["march 6"]) +if __name__ == '__main__': + t = HashTable() + t["march 6"] = 310 + print(t["march 6"]) + print(t["march 10"]) + del t["march 6"] + print(t["march 6"]) # lookup by key: O(1) on average # insertion/deletion: O(1) on average From 6b86e23bee72e08b0f11d46cd62b32a6d23fc902 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Sun, 2 Jan 2022 00:08:32 -0600 Subject: [PATCH 16/30] added helper function to make code faster and cleaner --- .../4_HashTable_2_Collisions/hash_table.py | 128 +++++++++--------- 1 file changed, 61 insertions(+), 67 deletions(-) diff --git a/data_structures/4_HashTable_2_Collisions/hash_table.py b/data_structures/4_HashTable_2_Collisions/hash_table.py index 818938d..ccb99e4 100644 --- a/data_structures/4_HashTable_2_Collisions/hash_table.py +++ b/data_structures/4_HashTable_2_Collisions/hash_table.py @@ -97,76 +97,43 @@ def get_hash(self, key): hash += ord(char) return hash % self.MAX + # returns the list of all indexs + # that need being probed + def get_prob_range(self, index): + return [*range(index, len(self.arr))] + [*range(0, index)] + def __getitem__(self, key): - arr_index = self.get_hash(key) - if self.arr[arr_index][0] == key: - return self.arr[arr_index][1] - else: - found = False - if arr_index + 1 == self.MAX: - idx = 0 - else: - idx = arr_index + 1 - while (not found and idx != arr_index): - if self.arr[idx][0] == key: - found = True - return self.arr[idx][1] - else: - if idx + 1 == self.MAX: - idx = 0 - else: - idx += 1 + # new solution with helper function + # need to search all prob range because + # there might have been a case that some entries between + # were deleted after the item was set + h = self.get_hash(key) + for i in self.get_prob_range(h): + if self.arr[i][0] == key: + return self.arr[i][1] + return def __setitem__(self, key, val): h = self.get_hash(key) - if self.arr[h][0] in (key, None): - self.arr[h] = (key, val) - else: - if h + 1 == self.MAX: - idx = 0 - else: - idx = h + 1 - new_idx = None - found = False - while not found and idx != h: - target = self.arr[idx][0] - if target == key: - found = True - self.arr[idx] = (key, val) - else: - if target == None and new_idx == None: - new_idx = idx - if idx + 1 == self.MAX: - idx = 0 - else: - idx += 1 - if not found: - if new_idx == None: - raise Exception("Hashmap is full") - else: - self.arr[new_idx] = (key, val) - - # Problem) deleted position should have (None, None) but - # it just deletes the one entry + set = False + for i in self.get_prob_range(h): + if self.arr[i][0] == key: + self.arr[i] = (key, val) + set = True + return + for i in self.get_prob_range(h): + if self.arr[i][0] == None: + self.arr[i] = (key, val) + set = True + return + if not set: + raise Exception("Hashmap is full") + def __delitem__(self, key): - arr_index = self.get_hash(key) - if self.arr[arr_index][0] == key: - del self.arr[arr_index] - else: - found = False - if arr_index + 1 == self.MAX: - idx = 0 - else: - idx = arr_index + 1 - while (not found and idx != arr_index): - if self.arr[idx][0] == key: - found = True - self.arr[idx] = (None, None) - else: - if idx + 1 == self.MAX: - idx = 0 - else: - idx += 1 + h = self.get_hash(key) + for i in self.get_prob_range(h): + if self.arr[i][0] == key: + self.arr[i] = (None, None) print("\nExercise Problem 4)") @@ -174,7 +141,35 @@ def __delitem__(self, key): Even took care of the corner case that the solution didn't take care of,\n\ which is get or set item that has been stored at somewhere else when the arr[h] gets deleted.\n\ Lesson learned: use helper fuction!!!! (the current code is too hard to read)") -''' + + +# this test below(using march 9, 10, 29) is +# what the given solution code fails to pass + +print("\ntest 1) getting item correctly after some deletions") +test1 = HashTable() +print(test1.get_hash("march 9")) +print(test1.get_hash("march 10")) +print(test1.get_hash("march 29")) +test1["march 9"] = 1 +test1["march 10"] = 2 +test1["march 29"] = 3 +print(test1.arr) +del test1["march 9"] +print(test1["march 10"]) +print(test1.arr) + +print("\ntest 2) setting item correctly after some deletions") +test2 = HashTable() +test2["march 9"] = 1 +test2["march 10"] = 2 +test2["march 29"] = 3 +del test2["march 10"] +test2["march 29"] = 100 +print(test2.arr) + + +print("\nmore tests)") t = HashTable() t["march 6"] = 20 t["march 17"] = 88 @@ -204,4 +199,3 @@ def __delitem__(self, key): # t["Jan 1"] = 0 --> raise exception del t["april 2"] print(t.arr) -''' From 6f36719b4a8239927744f2580f353048045b65b1 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Sun, 2 Jan 2022 00:09:13 -0600 Subject: [PATCH 17/30] added more tests that are failing to pass with the given solution code --- .../exercise_hash_table_linear_probing.ipynb | 193 +++++++++++++++--- 1 file changed, 164 insertions(+), 29 deletions(-) diff --git a/data_structures/4_HashTable_2_Collisions/Solution/exercise_hash_table_linear_probing.ipynb b/data_structures/4_HashTable_2_Collisions/Solution/exercise_hash_table_linear_probing.ipynb index 88f9122..ef98ec8 100644 --- a/data_structures/4_HashTable_2_Collisions/Solution/exercise_hash_table_linear_probing.ipynb +++ b/data_structures/4_HashTable_2_Collisions/Solution/exercise_hash_table_linear_probing.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 115, + "execution_count": 125, "metadata": {}, "outputs": [], "source": [ @@ -68,6 +68,141 @@ " print(self.arr)" ] }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 126, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# test1 shows failing to get item\n", + "test1 = HashTable()\n", + "test1.get_hash(\"march 9\")" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 127, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test1.get_hash(\"march 10\")" + ] + }, + { + "cell_type": "code", + "execution_count": 128, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 128, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test1.get_hash(\"march 29\")" + ] + }, + { + "cell_type": "code", + "execution_count": 129, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[None, None, ('march 9', 1), None, None, None, None, None, None, None]\n", + "[None, None, ('march 9', 1), ('march 10', 2), None, None, None, None, None, None]\n", + "[None, None, ('march 9', 1), ('march 10', 2), ('march 29', 3), None, None, None, None, None]\n" + ] + } + ], + "source": [ + "\n", + "test1[\"march 9\"] = 1\n", + "test1[\"march 10\"] = 2\n", + "test1[\"march 29\"] = 3" + ] + }, + { + "cell_type": "code", + "execution_count": 130, + "metadata": {}, + "outputs": [], + "source": [ + "del test1[\"march 9\"]\n", + "test1[\"march 10\"] # failing to get item correctly" + ] + }, + { + "cell_type": "code", + "execution_count": 149, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[None, None, ('march 9', 1), None, None, None, None, None, None, None]\n", + "[None, None, ('march 9', 1), ('march 10', 2), None, None, None, None, None, None]\n", + "[None, None, ('march 9', 1), ('march 10', 2), ('march 29', 3), None, None, None, None, None]\n" + ] + } + ], + "source": [ + "# test2 shows failing to set item\n", + "test2 = HashTable()\n", + "test2[\"march 9\"] = 1\n", + "test2[\"march 10\"] = 2\n", + "test2[\"march 29\"] = 3" + ] + }, + { + "cell_type": "code", + "execution_count": 151, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[None, None, ('march 9', 1), ('march 29', 100), ('march 29', 3), None, None, None, None, None]\n" + ] + } + ], + "source": [ + "del test2[\"march 10\"]\n", + "test2[\"march 29\"] = 100 # failing to set item correctly" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -77,7 +212,7 @@ }, { "cell_type": "code", - "execution_count": 116, + "execution_count": 132, "metadata": { "scrolled": true }, @@ -88,7 +223,7 @@ "[5, 6, 7, 0, 1, 2, 3]" ] }, - "execution_count": 116, + "execution_count": 132, "metadata": {}, "output_type": "execute_result" } @@ -99,7 +234,7 @@ }, { "cell_type": "code", - "execution_count": 117, + "execution_count": 133, "metadata": {}, "outputs": [ { @@ -119,7 +254,7 @@ }, { "cell_type": "code", - "execution_count": 118, + "execution_count": 134, "metadata": {}, "outputs": [ { @@ -136,7 +271,7 @@ }, { "cell_type": "code", - "execution_count": 119, + "execution_count": 135, "metadata": {}, "outputs": [ { @@ -153,7 +288,7 @@ }, { "cell_type": "code", - "execution_count": 120, + "execution_count": 136, "metadata": {}, "outputs": [ { @@ -170,7 +305,7 @@ }, { "cell_type": "code", - "execution_count": 121, + "execution_count": 137, "metadata": {}, "outputs": [], "source": [ @@ -179,7 +314,7 @@ }, { "cell_type": "code", - "execution_count": 122, + "execution_count": 138, "metadata": {}, "outputs": [ { @@ -188,7 +323,7 @@ "234" ] }, - "execution_count": 122, + "execution_count": 138, "metadata": {}, "output_type": "execute_result" } @@ -199,7 +334,7 @@ }, { "cell_type": "code", - "execution_count": 123, + "execution_count": 139, "metadata": { "scrolled": true }, @@ -218,7 +353,7 @@ }, { "cell_type": "code", - "execution_count": 124, + "execution_count": 140, "metadata": {}, "outputs": [ { @@ -227,7 +362,7 @@ "999" ] }, - "execution_count": 124, + "execution_count": 140, "metadata": {}, "output_type": "execute_result" } @@ -238,7 +373,7 @@ }, { "cell_type": "code", - "execution_count": 125, + "execution_count": 141, "metadata": { "scrolled": true }, @@ -257,7 +392,7 @@ }, { "cell_type": "code", - "execution_count": 126, + "execution_count": 142, "metadata": {}, "outputs": [ { @@ -274,7 +409,7 @@ }, { "cell_type": "code", - "execution_count": 127, + "execution_count": 143, "metadata": { "scrolled": true }, @@ -293,7 +428,7 @@ }, { "cell_type": "code", - "execution_count": 128, + "execution_count": 144, "metadata": {}, "outputs": [ { @@ -310,7 +445,7 @@ }, { "cell_type": "code", - "execution_count": 129, + "execution_count": 145, "metadata": {}, "outputs": [ { @@ -327,7 +462,7 @@ }, { "cell_type": "code", - "execution_count": 130, + "execution_count": 146, "metadata": {}, "outputs": [ { @@ -344,7 +479,7 @@ }, { "cell_type": "code", - "execution_count": 131, + "execution_count": 147, "metadata": { "scrolled": true }, @@ -354,12 +489,12 @@ "evalue": "Hashmap full", "output_type": "error", "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mException\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mt\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m\"Jan 1\"\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;32m\u001b[0m in \u001b[0;36m__setitem__\u001b[1;34m(self, key, val)\u001b[0m\n\u001b[0;32m 27\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marr\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mh\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mval\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 28\u001b[0m \u001b[1;32melse\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 29\u001b[1;33m \u001b[0mnew_h\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mfind_slot\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mh\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 30\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marr\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mnew_h\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mval\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 31\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marr\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;32m\u001b[0m in \u001b[0;36mfind_slot\u001b[1;34m(self, key, index)\u001b[0m\n\u001b[0;32m 41\u001b[0m \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0marr\u001b[0m\u001b[1;33m[\u001b[0m\u001b[0mprob_index\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;36m0\u001b[0m\u001b[1;33m]\u001b[0m \u001b[1;33m==\u001b[0m \u001b[0mkey\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 42\u001b[0m \u001b[1;32mreturn\u001b[0m \u001b[0mprob_index\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 43\u001b[1;33m \u001b[1;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Hashmap full\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 44\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 45\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0m__delitem__\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n", - "\u001b[1;31mException\u001b[0m: Hashmap full" + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mException\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/var/folders/nk/nzndlkn14wx_mdp2_t31tqmc0000gn/T/ipykernel_88106/1223874474.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mt\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m\"Jan 1\"\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/var/folders/nk/nzndlkn14wx_mdp2_t31tqmc0000gn/T/ipykernel_88106/176672100.py\u001b[0m in \u001b[0;36m__setitem__\u001b[0;34m(self, key, val)\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mh\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mval\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 29\u001b[0;31m \u001b[0mnew_h\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfind_slot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mh\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 30\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mnew_h\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mval\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 31\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/var/folders/nk/nzndlkn14wx_mdp2_t31tqmc0000gn/T/ipykernel_88106/176672100.py\u001b[0m in \u001b[0;36mfind_slot\u001b[0;34m(self, key, index)\u001b[0m\n\u001b[1;32m 41\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mprob_index\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 42\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mprob_index\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 43\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mException\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Hashmap full\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 44\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 45\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m__delitem__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mException\u001b[0m: Hashmap full" ] } ], @@ -369,7 +504,7 @@ }, { "cell_type": "code", - "execution_count": 133, + "execution_count": null, "metadata": { "scrolled": true }, @@ -388,7 +523,7 @@ }, { "cell_type": "code", - "execution_count": 134, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -420,7 +555,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.9.5" } }, "nbformat": 4, From be4814837e525983c78be8ed5df463388e1d0075 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Sun, 2 Jan 2022 00:10:44 -0600 Subject: [PATCH 18/30] commented out lines for testing --- data_structures/4_HashTable_2_Collisions/hash_table.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/data_structures/4_HashTable_2_Collisions/hash_table.py b/data_structures/4_HashTable_2_Collisions/hash_table.py index ccb99e4..e794608 100644 --- a/data_structures/4_HashTable_2_Collisions/hash_table.py +++ b/data_structures/4_HashTable_2_Collisions/hash_table.py @@ -143,10 +143,10 @@ def __delitem__(self, key): Lesson learned: use helper fuction!!!! (the current code is too hard to read)") -# this test below(using march 9, 10, 29) is -# what the given solution code fails to pass - +""" print("\ntest 1) getting item correctly after some deletions") +# this two tests below(using march 9, 10, 29) are +# what the given solution code fails to pass test1 = HashTable() print(test1.get_hash("march 9")) print(test1.get_hash("march 10")) @@ -199,3 +199,4 @@ def __delitem__(self, key): # t["Jan 1"] = 0 --> raise exception del t["april 2"] print(t.arr) +""" From 13f0d8f5551ec748b79f6e33c6e7d4bc7f574b58 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Sun, 2 Jan 2022 00:59:30 -0600 Subject: [PATCH 19/30] answers for stack practice probs --- data_structures/5_Stack/stack.py | 59 ++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/data_structures/5_Stack/stack.py b/data_structures/5_Stack/stack.py index 86a71df..5bf4b48 100644 --- a/data_structures/5_Stack/stack.py +++ b/data_structures/5_Stack/stack.py @@ -6,6 +6,24 @@ reverse_string("We will conquere COVID-19") should return "91-DIVOC ereuqnoc lliw eW" ''' +from collections import deque + + +def reverse_string(str): + reversed = "" + stack = deque() + stack.extend(str) + l = len(stack) + while l != 0: + reversed += stack.pop() + l -= 1 + return reversed + + +r1 = reverse_string("hello") +print(f"reverse string of hello: {r1}") +r2 = reverse_string("We will conquere COVID-19") +print(f"reverse string of We will conquere COVID-19: {r2}") ''' 2. Write a function in python that checks if paranthesis in the string are balanced or not. @@ -19,3 +37,44 @@ is_balanced("[a+b]*(x+2y)*{gg+kk}") --> True ''' + + +def is_match(chr): + dict = {'}': '{', ']': '[', ')': '('} + return dict[chr] + + +def is_balanced(str): + stack = deque() + for chr in str: + if chr in "{([": + stack.append(chr) + if chr in "})]": + if len(stack) == 0 or is_match(chr) != stack.pop(): + return False + return len(stack) == 0 + """ + # first solution I wrote has a problem + # it doesn't consider when it has equal number of parenthese each side but not the wrong one + # {[}] --> gives me True, which is False indeed + stack = deque() + for chr in str: + if chr in "{([": + stack.append(chr) + if chr in "})]": + try: + stack.pop() + except IndexError: + return False + return len(stack) == 0 + """ + + +print("is_balanced(\"({a+b}))\"): " + str(is_balanced("({a+b})"))) +print("is_balanced(\"))((a+b}{\"): " + str(is_balanced("))((a+b}{"))) +print("is_balanced(\"((a+b))\"): " + str(is_balanced("((a+b))"))) +print("is_balanced(\"))\"): " + str(is_balanced("))"))) +print("is_balanced(\"[a+b]*(x+2y)*{gg+kk}\") : " + + str(is_balanced("[a+b]*(x+2y)*{gg+kk}"))) + +print("is_balanced(\"({a+b)})\"): " + str(is_balanced("({a+b)}"))) From 08595ee4c07f23d8f4f4e48d2205cae5b5736c6c Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 3 Jan 2022 02:32:07 -0600 Subject: [PATCH 20/30] answers for queue practice probs --- data_structures/6_Queue/6_queue.ipynb | 100 ++++++++++++++++++-------- data_structures/6_Queue/myqueue.py | 70 ++++++++++++++++++ data_structures/6_Queue/queue.py | 45 ------------ 3 files changed, 139 insertions(+), 76 deletions(-) create mode 100644 data_structures/6_Queue/myqueue.py delete mode 100644 data_structures/6_Queue/queue.py diff --git a/data_structures/6_Queue/6_queue.ipynb b/data_structures/6_Queue/6_queue.ipynb index 325ddb5..81729b4 100644 --- a/data_structures/6_Queue/6_queue.ipynb +++ b/data_structures/6_Queue/6_queue.ipynb @@ -16,7 +16,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -25,7 +25,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -36,7 +36,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -45,7 +45,7 @@ "[135, 132.12, 131.1]" ] }, - "execution_count": 6, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -56,7 +56,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -65,7 +65,7 @@ "131.1" ] }, - "execution_count": 7, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -76,7 +76,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -85,7 +85,7 @@ "[135, 132.12]" ] }, - "execution_count": 8, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -96,7 +96,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -105,7 +105,7 @@ "132.12" ] }, - "execution_count": 9, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -116,7 +116,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -125,7 +125,7 @@ "135" ] }, - "execution_count": 10, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -136,7 +136,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -144,10 +144,10 @@ "evalue": "pop from empty list", "output_type": "error", "traceback": [ - "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[1;31mIndexError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m\u001b[0m in \u001b[0;36m\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mwmt_stock_price_queue\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpop\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[1;31mIndexError\u001b[0m: pop from empty list" + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/var/folders/nk/nzndlkn14wx_mdp2_t31tqmc0000gn/T/ipykernel_96232/1260761002.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mwmt_stock_price_queue\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m: pop from empty list" ] } ], @@ -164,7 +164,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -174,7 +174,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -197,7 +197,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -217,7 +217,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -237,7 +237,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -257,7 +257,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -275,9 +275,14 @@ "q.pop()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "scrolled": true }, @@ -307,11 +312,13 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "from collections import deque\n", + "import time\n", + "import threading\n", "\n", "class Queue:\n", " \n", @@ -328,12 +335,43 @@ " return len(self.buffer)==0\n", " \n", " def size(self):\n", - " return len(self.buffer)" + " return len(self.buffer)\n", + "\n", + " def place_order(self, orders):\n", + " for order in orders:\n", + " self.enqueue(order)\n", + " time.sleep(0.5)\n", + "\n", + " def serve_order(self):\n", + " while not self.is_empty:\n", + " time.sleep(2)\n", + " print(self.dequeue())\n", + "\n", + " def food_ordering_system(self, orders):\n", + " q = Queue()\n", + " t1 = threading.Thread(target=q.place_order, args=(orders,))\n", + " t2 = threading.Thread(target=q.serve_order)\n", + " t1.start()\n", + " time.sleep(1)\n", + " t2.start()\n", + " t1.join()\n", + " t2.join()" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "orders = ['pizza', 'samosa', 'pasta', 'biryani', 'burger']\n", + "q = Queue()\n", + "q.food_ordering_system(orders)" ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -358,7 +396,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -378,7 +416,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -398,7 +436,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -433,7 +471,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.9.5" } }, "nbformat": 4, diff --git a/data_structures/6_Queue/myqueue.py b/data_structures/6_Queue/myqueue.py new file mode 100644 index 0000000..d5762c9 --- /dev/null +++ b/data_structures/6_Queue/myqueue.py @@ -0,0 +1,70 @@ +# Data structure tutorial exercise: Queue +from collections import deque +import threading +import time + + +class Queue: + + def __init__(self): + self.buffer = deque() + + def enqueue(self, val): + self.buffer.appendleft(val) + + def dequeue(self): + return self.buffer.pop() + + def is_empty(self): + return len(self.buffer) == 0 + + def size(self): + return len(self.buffer) + + # exercise prob 1) food ordering system + + def place_order(self, orders): + for order in orders: + self.enqueue(order) + time.sleep(0.5) + + def serve_order(self): + while not self.is_empty: + time.sleep(2) + print(self.dequeue()) + + def food_ordering_system(self, orders): + q = Queue() + t1 = threading.Thread(target=q.place_order, args=(orders,)) + t2 = threading.Thread(target=q.serve_order) + t1.start() + time.sleep(1) + t2.start() + t1.join() + t2.join() + + # exercise prob 2) print binary numbers from 1 to 10 + + def front(self): + return self.buffer.popleft() + + +def binary_numbers(n): + q = Queue() + q.enqueue('1') + entry = None + for i in range(n): + entry = q.dequeue() + print(entry) + q.enqueue(entry + '0') + q.enqueue(entry + '1') + + +if __name__ == '__main__': + # exercise prob 1) + orders = ['pizza', 'samosa', 'pasta', 'biryani', 'burger'] + q = Queue() + q.food_ordering_system(orders) # not sure how to test + + # exercise prob 2) + binary_numbers(10) diff --git a/data_structures/6_Queue/queue.py b/data_structures/6_Queue/queue.py deleted file mode 100644 index 6d9311a..0000000 --- a/data_structures/6_Queue/queue.py +++ /dev/null @@ -1,45 +0,0 @@ -# Data structure tutorial exercise: Queue - -''' -1. Design a food ordering system where your python program will run two threads, - 1. Place Order: This thread will be placing an order and inserting that into a queue. - This thread places new order every 0.5 second. (hint: use time.sleep(0.5) function) - 2. Serve Order: This thread will server the order. - All you need to do is pop the order out of the queue and print it. - This thread serves an order every 2 seconds. - Also start this thread 1 second after place order thread is started. - - Use this video to get yourself familiar with [multithreading in python - (https://www.youtube.com/watch?v=PJ4t2U15ACo&list=PLeo1K3hjS3uub3PRhdoCTY8BxMKSW7RjN&index=2&t=0s) - - Pass following list as an argument to place order thread, - - orders = ['pizza','samosa','pasta','biryani','burger'] - - This problem is a producer,consumer problem - where place_order thread is producing orders whereas server_order thread is consuming the food orders. - Use Queue class implemented in a video tutorial. -''' - -''' -2. Write a program to print binary numbers from 1 to 10 using Queue. -Use Queue class implemented in main tutorial. -Binary sequence should look like, - - 1 - 10 - 11 - 100 - 101 - 110 - 111 - 1000 - 1001 - 1010 - -Hint: Notice a pattern above. -After 1 second and third number is 1+0 and 1+1. -4th and 5th number are second number (i.e. 10) + 0 and second number (i.e. 10) + 1. - -You also need to add front() function in queue class that can return the front element in the queue. -''' From ed8f2cae05e4762a90f491c40fdf7bda8afb31eb Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 3 Jan 2022 02:33:19 -0600 Subject: [PATCH 21/30] made it cleaner --- data_structures/6_Queue/myqueue.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/data_structures/6_Queue/myqueue.py b/data_structures/6_Queue/myqueue.py index d5762c9..570a12d 100644 --- a/data_structures/6_Queue/myqueue.py +++ b/data_structures/6_Queue/myqueue.py @@ -43,16 +43,11 @@ def food_ordering_system(self, orders): t1.join() t2.join() - # exercise prob 2) print binary numbers from 1 to 10 - - def front(self): - return self.buffer.popleft() - +# exercise prob 2) print binary numbers from 1 to 10 def binary_numbers(n): q = Queue() q.enqueue('1') - entry = None for i in range(n): entry = q.dequeue() print(entry) From 54b03350568edb25373948989016d6550ed3228e Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 3 Jan 2022 11:17:27 -0600 Subject: [PATCH 22/30] answers for tree practice probs --- data_structures/7_Tree/7_tree.py | 107 +++++++++++++++++- .../7_Tree/Exercise/location_hierarchy.py | 5 +- data_structures/7_Tree/tree.py | 1 - 3 files changed, 105 insertions(+), 8 deletions(-) delete mode 100644 data_structures/7_Tree/tree.py diff --git a/data_structures/7_Tree/7_tree.py b/data_structures/7_Tree/7_tree.py index 02d977d..340607f 100644 --- a/data_structures/7_Tree/7_tree.py +++ b/data_structures/7_Tree/7_tree.py @@ -1,6 +1,6 @@ class TreeNode: - def __init__(self, data): - self.data = data + def __init__(self, name, designation=''): + self.data = {'name': name, 'designation': designation} self.children = [] self.parent = None @@ -16,15 +16,42 @@ def get_level(self): def print_tree(self): spaces = ' ' * self.get_level() * 3 prefix = spaces + "|__" if self.parent else "" - print(prefix + self.data) + print(prefix + self.data['name']) if self.children: for child in self.children: child.print_tree() + def print_tree_ex1(self, option): + spaces = ' ' * self.get_level() * 3 + prefix = spaces + "|__" if self.parent else "" + if option == "both": + print(prefix + self.data['name'] + + " (" + self.data['designation'] + ")") + elif option in ("name", "designation"): + print(prefix + self.data[option]) + else: + raise Exception("Invalid option") + if self.children: + for child in self.children: + child.print_tree_ex1(option) + + def print_tree_ex2(self, level): + lv = self.get_level() + spaces = ' ' * lv * 3 + prefix = spaces + "|__" if self.parent else "" + print(prefix + self.data['name']) + if level == lv: + return + else: + if self.children: + for child in self.children: + child.print_tree_ex2(level) + def add_child(self, child): child.parent = self self.children.append(child) + def build_product_tree(): root = TreeNode("Electronics") @@ -48,5 +75,77 @@ def build_product_tree(): root.print_tree() +# exercise prob 1) company hierarchy tree + + +def build_management_tree(): + ceo = TreeNode("Nilupul", "CEO") + cto = TreeNode("Chinmay", "CTO") + hr = TreeNode("Gels", "HR Head") + ceo.add_child(cto) + ceo.add_child(hr) + + infra = TreeNode("Vishwa", "Infrastructure Head") + cto.add_child(infra) + cto.add_child(TreeNode("Aamir", "Application Head")) + infra.add_child(TreeNode("Dhaval", "Cloud Manager")) + infra.add_child(TreeNode("Abhijit", "App Manager")) + + hr.add_child(TreeNode("Peter", "Recruitment Manager")) + hr.add_child(TreeNode("Waqas", "Policy Manager")) + + return ceo + +# exercise prob 2) location tree + + +def build_location_tree(): + root = TreeNode("Global") + + india = TreeNode("India") + gujarat = TreeNode("Gujarat") + gujarat.add_child(TreeNode("Ahmedabad")) + gujarat.add_child(TreeNode("Baroda")) + karnataka = TreeNode("Karnataka") + karnataka.add_child(TreeNode("Bangluru")) + karnataka.add_child(TreeNode("Mysore")) + india.add_child(gujarat) + india.add_child(karnataka) + + usa = TreeNode("USA") + nj = TreeNode("New Jersey") + nj.add_child(TreeNode("Princeton")) + nj.add_child(TreeNode("Trenton")) + ca = TreeNode("California") + ca.add_child(TreeNode("San Francisco")) + ca.add_child(TreeNode("Mountain View")) + ca.add_child(TreeNode("Palo Alto")) + usa.add_child(nj) + usa.add_child(ca) + + root.add_child(india) + root.add_child(usa) + + return root + + if __name__ == '__main__': - build_product_tree() \ No newline at end of file + build_product_tree() + + print("\n- - - - - - - - - - - - - - - - -\n") + + # exercise prob 1) + # extend data and print tree with options, name, designation, both + root_node_1 = build_management_tree() + root_node_1.print_tree_ex1("name") # prints only name hierarchy + # prints only designation hierarchy + root_node_1.print_tree_ex1("designation") + # prints both (name and designation) hierarchy + root_node_1.print_tree_ex1("both") + + print("\n- - - - - - - - - - - - - - - - -\n") + + # exercise prob 2) + # build location tree and print tree with tree level + root_node_2 = build_location_tree() + root_node_2.print_tree_ex2(2) diff --git a/data_structures/7_Tree/Exercise/location_hierarchy.py b/data_structures/7_Tree/Exercise/location_hierarchy.py index 1b9232e..05c125a 100644 --- a/data_structures/7_Tree/Exercise/location_hierarchy.py +++ b/data_structures/7_Tree/Exercise/location_hierarchy.py @@ -27,6 +27,7 @@ def add_child(self, child): child.parent = self self.children.append(child) + def build_location_tree(): root = TreeNode("Global") @@ -65,6 +66,4 @@ def build_location_tree(): if __name__ == '__main__': root_node = build_location_tree() - root_node.print_tree(3) - - + root_node.print_tree(5) diff --git a/data_structures/7_Tree/tree.py b/data_structures/7_Tree/tree.py deleted file mode 100644 index 584cc28..0000000 --- a/data_structures/7_Tree/tree.py +++ /dev/null @@ -1 +0,0 @@ -# Data structure tutorial exercise: General Tree From c05e9c2e0b375c7d726831e7ebb9cb1a6eb0b057 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 3 Jan 2022 16:27:45 -0600 Subject: [PATCH 23/30] answers for binary tree (part 1) practice probs --- .../8_Binary_Tree_1/binary_tree_part_1.py | 88 ++++++++++++++++--- 1 file changed, 77 insertions(+), 11 deletions(-) diff --git a/data_structures/8_Binary_Tree_1/binary_tree_part_1.py b/data_structures/8_Binary_Tree_1/binary_tree_part_1.py index f162761..1bfd05b 100644 --- a/data_structures/8_Binary_Tree_1/binary_tree_part_1.py +++ b/data_structures/8_Binary_Tree_1/binary_tree_part_1.py @@ -47,6 +47,54 @@ def in_order_traversal(self): return elements + # practice problems - implement five methods below + + # finds minimum element in entire binary tree + def find_min(self): + if self.left: + return self.left.find_min() + else: + return self.data + + # finds maximum element in entire binary tree + + def find_max(self): + if self.right: + return self.right.find_max() + else: + return self.data + + # calcualtes sum of all elements + def calculate_sum(self): + sum = self.data + if self.left: + sum += self.left.calculate_sum() + if self.right: + sum += self.right.calculate_sum() + return sum + + # perofrms pre order traversal of a binary tree + def pre_order_traversal(self): + elements = [] + elements.append(self.data) + + if self.left: + elements += self.left.pre_order_traversal() + if self.right: + elements += self.right.pre_order_traversal() + return elements + + # performs post order traversal of a binary tree + def post_order_traversal(self): + elements = [] + if self.left: + elements += self.left.post_order_traversal() + if self.right: + elements += self.right.post_order_traversal() + + elements.append(self.data) + return elements + def build_tree(elements): print("Building tree with these elements:", elements) @@ -58,17 +106,6 @@ def build_tree(elements): return root -''' -Add following methods to [BinarySearchTreeNode class](https://github.com/codebasics/data-structures-algorithms-python/blob/master/data_structures/8_Binary_Tree_1/binary_tree_part_1.py) created in main video tutorial - - 1. find_min(): finds minimum element in entire binary tree - 2. find_max(): finds maximum element in entire binary tree - 3. calculate_sum(): calcualtes sum of all elements - 4. post_order_traversal(): performs post order traversal of a binary tree - 5. pre_order_traversal(): perofrms pre order traversal of a binary tree -''' - - if __name__ == '__main__': countries = ["India", "Pakistan", "Germany", "USA", "China", "India", "UK", "USA"] @@ -80,3 +117,32 @@ def build_tree(elements): numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) print("In order traversal gives this sorted list:", numbers_tree.in_order_traversal()) + + print("\n- - - - - - - - - - - - - - - - -\n") + + print(numbers_tree.find_min()) + print(numbers_tree.find_max()) + + print(sum([17, 4, 1, 20, 9, 23, 18, 34])) + print(numbers_tree.calculate_sum()) + + print("Pre order traversal gives this sorted list:", + numbers_tree.pre_order_traversal()) + + print("Post order traversal gives this sorted list:", + numbers_tree.post_order_traversal()) + + print("\n- - - - - - - - - - - - - - - - -\n") + + numbers = [17, 4, 1, 20, 9, 23, 18, 34] + + numbers = [15, 12, 7, 14, 27, 20, 23, 88] + + numbers_tree = build_tree(numbers) + print("Input numbers:", numbers) + print("Min:", numbers_tree.find_min()) + print("Max:", numbers_tree.find_max()) + print("Sum:", numbers_tree.calculate_sum()) + print("In order traversal:", numbers_tree.in_order_traversal()) + print("Pre order traversal:", numbers_tree.pre_order_traversal()) + print("Post order traversal:", numbers_tree.post_order_traversal()) From 2741e88de12aa081a18ece04d3c4dc0846ed7cb7 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 3 Jan 2022 17:29:33 -0600 Subject: [PATCH 24/30] answers for binary tree (part 2) practice probs --- .../9_Binary_Tree_2/binary_tree_part_2.py | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/data_structures/9_Binary_Tree_2/binary_tree_part_2.py b/data_structures/9_Binary_Tree_2/binary_tree_part_2.py index 8a4a4a5..7c6ba3d 100644 --- a/data_structures/9_Binary_Tree_2/binary_tree_part_2.py +++ b/data_structures/9_Binary_Tree_2/binary_tree_part_2.py @@ -6,7 +6,7 @@ def __init__(self, data): def add_child(self, data): if data == self.data: - return # node already exist + return # node already exist if data < self.data: if self.left: @@ -19,7 +19,6 @@ def add_child(self, data): else: self.right = BinarySearchTreeNode(data) - def search(self, val): if self.data == val: return True @@ -62,10 +61,17 @@ def delete(self, val): return self.right elif self.right is None: return self.left - + ''' min_val = self.right.find_min() self.data = min_val self.right = self.right.delete(min_val) + ''' + # if the node to be deletedd has two children + # it has to copy one from children + # and delete the duplicated node from children + max_val = self.left.find_max() + self.data = max_val + self.left = self.left.delete(max_val) return self @@ -81,23 +87,34 @@ def find_min(self): def build_tree(elements): - print("Building tree with these elements:",elements) + print("Building tree with these elements:", elements) root = BinarySearchTreeNode(elements[0]) - for i in range(1,len(elements)): + for i in range(1, len(elements)): root.add_child(elements[i]) return root + if __name__ == '__main__': numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) numbers_tree.delete(20) - print("After deleting 20 ",numbers_tree.in_order_traversal()) # this should print [1, 4, 9, 17, 18, 23, 34] + # this should print [1, 4, 9, 17, 18, 23, 34] + print("After deleting 20 ", numbers_tree.in_order_traversal()) numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) numbers_tree.delete(9) - print("After deleting 9 ",numbers_tree.in_order_traversal()) # this should print [1, 4, 17, 18, 20, 23, 34] + # this should print [1, 4, 17, 18, 20, 23, 34] + print("After deleting 9 ", numbers_tree.in_order_traversal()) numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) numbers_tree.delete(17) - print("After deleting 17 ",numbers_tree.in_order_traversal()) # this should print [1, 4, 9, 18, 20, 23, 34] + # this should print [1, 4, 9, 18, 20, 23, 34] + print("After deleting 17 ", numbers_tree.in_order_traversal()) + + print("\n- - - - - - - - - - - - - - - - -\n") + + numbers_tree = build_tree([17, 4, 1, 20, 9, 23, 18, 34]) + numbers_tree.delete(10) + print("After deleting 10 (non-existent node) ", + numbers_tree.in_order_traversal()) From 24bcb7eb9d0712fc8165c95574414375162f544b Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Mon, 3 Jan 2022 18:11:29 -0600 Subject: [PATCH 25/30] todo: reimplement get_paths, get_shortest_path --- data_structures/10_Graph/mygraph.py | 53 +++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 data_structures/10_Graph/mygraph.py diff --git a/data_structures/10_Graph/mygraph.py b/data_structures/10_Graph/mygraph.py new file mode 100644 index 0000000..5765a7a --- /dev/null +++ b/data_structures/10_Graph/mygraph.py @@ -0,0 +1,53 @@ +class Graph: + def __init__(self, edges): + self.edges = edges + self.graph_dict = {} + for start, end in edges: + if start in self.graph_dict: + self.graph_dict[start].append(end) + else: + self.graph_dict[start] = [end] + print("Graph Dict:", self.graph_dict) + + def get_paths(self, start, end, path=[]): + pass + + def get_shortest_path(self, start, end, path=[]): + pass + +if __name__ == '__main__': + + routes = [ + ("Mumbai","Pune"), + ("Mumbai", "Surat"), + ("Surat", "Bangaluru"), + ("Pune","Hyderabad"), + ("Pune","Mysuru"), + ("Hyderabad","Bangaluru"), + ("Hyderabad", "Chennai"), + ("Mysuru", "Bangaluru"), + ("Chennai", "Bangaluru") + ] + + routes = [ + ("Mumbai", "Paris"), + ("Mumbai", "Dubai"), + ("Paris", "Dubai"), + ("Paris", "New York"), + ("Dubai", "New York"), + ("New York", "Toronto"), + ] + + route_graph = Graph(routes) + + start = "Mumbai" + end = "New York" + + print(f"All paths between: {start} and {end}: ",route_graph.get_paths(start,end)) + print(f"Shortest path between {start} and {end}: ", route_graph.get_shortest_path(start,end)) + + start = "Dubai" + end = "New York" + + print(f"All paths between: {start} and {end}: ",route_graph.get_paths(start,end)) + print(f"Shortest path between {start} and {end}: ", route_graph.get_shortest_path(start,end)) From 7e3e5b5ca44d5e55aa65d12f43605a71d3286580 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Wed, 5 Jan 2022 18:17:32 -0600 Subject: [PATCH 26/30] answers for binary search practice probs --- algorithms/1_BinarySearch/binarysearch.py | 128 ++++++++++++++++++++-- 1 file changed, 120 insertions(+), 8 deletions(-) diff --git a/algorithms/1_BinarySearch/binarysearch.py b/algorithms/1_BinarySearch/binarysearch.py index ed3413e..263f0e4 100644 --- a/algorithms/1_BinarySearch/binarysearch.py +++ b/algorithms/1_BinarySearch/binarysearch.py @@ -1,13 +1,13 @@ from util import time_it -@time_it +# @time_it def linear_search(numbers_list, number_to_find): for index, element in enumerate(numbers_list): if element == number_to_find: return index return -1 -@time_it +# @time_it def binary_search(numbers_list, number_to_find): left_index = 0 right_index = len(numbers_list) - 1 @@ -32,8 +32,6 @@ def binary_search_recursive(numbers_list, number_to_find, left_index, right_inde return -1 mid_index = (left_index + right_index) // 2 - if mid_index >= len(numbers_list) or mid_index < 0: - return -1 mid_number = numbers_list[mid_index] @@ -47,9 +45,123 @@ def binary_search_recursive(numbers_list, number_to_find, left_index, right_inde return binary_search_recursive(numbers_list, number_to_find, left_index, right_index) +# @time_it +# my implementation for prob 2 -- the least efficient +def binary_search_for_all_occurences(numbers_list, number_to_find, left_index, right_index, result=[]): + if right_index < left_index: + return result + + mid_index = (left_index + right_index) // 2 + + mid_number = numbers_list[mid_index] + + if mid_number == number_to_find: + result.append(mid_index) + result_1 = binary_search_for_all_occurences(numbers_list, number_to_find, mid_index + 1, right_index, result) + result_2 = binary_search_for_all_occurences(numbers_list, number_to_find, left_index, mid_index - 1, result) + result = set(result_1).union(set(result_2)) + return result + + if mid_number < number_to_find: + left_index = mid_index + 1 + else: + right_index = mid_index - 1 + + return binary_search_for_all_occurences(numbers_list, number_to_find, left_index, right_index, result) + +@time_it +# the given solution for prob 2 -- not the most efficient +def find_all_occurances(numbers, number_to_find): + index = binary_search(numbers, number_to_find) + indices = [index] + # find indices on left hand side + i = index-1 + while i >=0: + if numbers[i] == number_to_find: + indices.append(i) + else: + break + i = i - 1 + + # find indices on right hand side + i = index + 1 + while i= mid_right: + if numbers_list[mid_right] == number_to_find: + result.append(mid_right) + else: + break + mid_right = mid_right + 1 + + return sorted(result) + + if mid_number < number_to_find: + left_index = mid_index + 1 + else: + right_index = mid_index - 1 + + return result + + if __name__ == '__main__': - numbers_list = [12, 15, 17, 19, 21, 24, 45, 67] - number_to_find = 21 + ''' + numbers_list_1 = [12, 15, 17, 19, 21, 24, 45, 67] + number_to_find_1 = 80 + + index_1 = binary_search_recursive(numbers_list_1, number_to_find_1, 0, len(numbers_list_1)-1) + print(f"Number found at index {index_1} using binary search") + + print("\n- - - - - - - - - - - - - - - - -\n") + ''' + + # exercise prob 1) + # ans: because binary search is for only sorted arrays + # (the given list [1,4,6,9,10,5,7] is not sorted, + # so if it tries to find 5, + # it will search [1, 4, 6] because 5 < 10, + # which leads to returning -1) + + # exercise prob 2) Find index of all the occurances of a number from sorted list + numbers_list_2 = [1,4,6,9,11,15,15,15,17,21,34,34,56] + number_to_find_2 = 15 + + index_2 = binary_search_for_all_occurences(numbers_list_2, number_to_find_2, 0, len(numbers_list_2)-1) + print(f"Number found at index {index_2} using my first least efficient way") + + index_s = find_all_occurances(numbers_list_2, number_to_find_2) + print(f"Number found at index {index_s} using the given solution") - index = binary_search_recursive(numbers_list, number_to_find, 0, len(numbers_list)) - print(f"Number found at index {index} using binary search") \ No newline at end of file + index_3 = find_all_efficient(numbers_list_2, number_to_find_2) + print(f"Number found at index {index_3} using my new efficient way") + \ No newline at end of file From 449de38c12e0c090f3bf197282e19da6ce049c12 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Fri, 7 Jan 2022 19:56:25 -0600 Subject: [PATCH 27/30] added time & space complexity --- algorithms/1_BinarySearch/binarysearch.py | 3 +++ algorithms/2_BubbleSort/bubble_sort.py | 3 +++ 2 files changed, 6 insertions(+) diff --git a/algorithms/1_BinarySearch/binarysearch.py b/algorithms/1_BinarySearch/binarysearch.py index 263f0e4..f61f2ff 100644 --- a/algorithms/1_BinarySearch/binarysearch.py +++ b/algorithms/1_BinarySearch/binarysearch.py @@ -1,5 +1,8 @@ from util import time_it +# time complexity: O(log n) +# space complexity: O(1) + # @time_it def linear_search(numbers_list, number_to_find): for index, element in enumerate(numbers_list): diff --git a/algorithms/2_BubbleSort/bubble_sort.py b/algorithms/2_BubbleSort/bubble_sort.py index c39aa87..cbd1226 100644 --- a/algorithms/2_BubbleSort/bubble_sort.py +++ b/algorithms/2_BubbleSort/bubble_sort.py @@ -1,4 +1,7 @@ +# time complexity: O(n^2) +# space complexity: O(1) + # you can use this to sort strings too def bubble_sort(elements): size = len(elements) From 17d2de163ba65c9eda5a67ca0ddc872bca6e44a6 Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Fri, 7 Jan 2022 20:12:40 -0600 Subject: [PATCH 28/30] answers for bubble sort practice probs --- algorithms/2_BubbleSort/bubble_sort.py | 41 +++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/algorithms/2_BubbleSort/bubble_sort.py b/algorithms/2_BubbleSort/bubble_sort.py index cbd1226..d94e1ea 100644 --- a/algorithms/2_BubbleSort/bubble_sort.py +++ b/algorithms/2_BubbleSort/bubble_sort.py @@ -17,7 +17,32 @@ def bubble_sort(elements): if not swapped: break +''' +exercise prob) +modify bubble sort s.t. it can sort following list of transactions with key +elements = [ + { 'name': 'mona', 'transaction_amount': 1000, 'device': 'iphone-10'}, + { 'name': 'dhaval', 'transaction_amount': 400, 'device': 'google pixel'}, + { 'name': 'kathy', 'transaction_amount': 200, 'device': 'vivo'}, + { 'name': 'aamir', 'transaction_amount': 800, 'device': 'iphone-8'}, + ] +''' +# elements: list of hash tables +def bubble_sort_exercise(elements, key): + size = len(elements) + + for i in range(size-1): + swapped = False + for j in range(size-1-i): + if elements[j][key] > elements[j+1][key]: + tmp = elements[j] + elements[j] = elements[j+1] + elements[j+1] = tmp + swapped = True + + if not swapped: + break if __name__ == '__main__': elements = [5,9,2,1,67,34,88,34] @@ -25,4 +50,18 @@ def bubble_sort(elements): elements = ["mona", "dhaval", "aamir", "tina", "chang"] bubble_sort(elements) - print(elements) \ No newline at end of file + print(elements) + + print("\n- - - - - - - - - - - - - - - - -\n") + + elements = [ + { 'name': 'mona', 'transaction_amount': 1000, 'device': 'iphone-10'}, + { 'name': 'dhaval', 'transaction_amount': 400, 'device': 'google pixel'}, + { 'name': 'kathy', 'transaction_amount': 200, 'device': 'vivo'}, + { 'name': 'aamir', 'transaction_amount': 800, 'device': 'iphone-8'}, + ] + + bubble_sort_exercise(elements, 'name') + print(f"sorted by name:\n{elements}\n") + bubble_sort_exercise(elements, 'transaction_amount') + print(f"sorted by transaction amount:\n{elements}\n") \ No newline at end of file From 8c7459f22a35f9b8d9664860680bab970a342cbe Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Sun, 13 Feb 2022 16:40:21 -0600 Subject: [PATCH 29/30] add .DS_Store --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2d15a85..f051805 100644 --- a/.gitignore +++ b/.gitignore @@ -129,4 +129,7 @@ dmypy.json .pyre/ # Editor settings -.vscode/settings.json \ No newline at end of file +.vscode/settings.json + + +.DS_Store From 465ea3cdb6f03d487fe701f77eab0ae8156931af Mon Sep 17 00:00:00 2001 From: Ellie Ko <70093034+ellieko@users.noreply.github.com> Date: Sun, 27 Feb 2022 13:05:03 -0600 Subject: [PATCH 30/30] working on lumoto --- algorithms/3_QuickSort/quick_sort.py | 37 +++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/algorithms/3_QuickSort/quick_sort.py b/algorithms/3_QuickSort/quick_sort.py index 36b7e73..4faca10 100644 --- a/algorithms/3_QuickSort/quick_sort.py +++ b/algorithms/3_QuickSort/quick_sort.py @@ -1,3 +1,8 @@ + +# average time complexity: O(nlogn) +# worst time complexity: O(n^2) +# space complexity: O() + # implementation of quick sort in python using hoare partition scheme def swap(a, b, arr): @@ -31,11 +36,35 @@ def partition(elements, start, end): return end +# implementation of quick sort in python using lumoto partition scheme (exercise prob) + +def quick_sort_lumoto(elements, low, high): + pass + +def partition_lumoto(elements, low, high): + pivot_index = high + pivot = elements[high] + while low != high : + while low < len(elements) and elements[low] <= pivot: + low += 1 + if low < len(elements): + high = low + while elements[high] > pivot: + high += 1 + if low < high: + swap(low, high, elements) + return pivot_index + + if __name__ == '__main__': elements = [11,9,29,7,2,15,28] # elements = ["mona", "dhaval", "aamir", "tina", "chang"] - quick_sort(elements, 0, len(elements)-1) + # quick_sort(elements, 0, len(elements)-1) + print(elements) + partition_lumoto(elements, 0, len(elements)-1) print(elements) + #partition_lumoto(elements, 1) + print(elements) tests = [ [11,9,29,7,2,15,28], @@ -48,6 +77,6 @@ def partition(elements, start, end): for elements in tests: quick_sort(elements, 0, len(elements)-1) - print(f'sorted array: {elements}') - - + print(f'sorted array by hoare partition: {elements}') + #quick_sort_lumoto(elements, 0, len(elements)-1) + #print(f'sorted array by lumoto partition: {elements}') \ No newline at end of file