From 8f02359b63a75a70bef2bf688d88edf46c7e0c97 Mon Sep 17 00:00:00 2001 From: WHAHA-HA Date: Sun, 9 Aug 2020 08:52:50 +0530 Subject: [PATCH] Formatted programs using black --- Solutions/01.py | 8 +- Solutions/02.py | 8 +- Solutions/03.py | 28 +++--- Solutions/04.py | 8 +- Solutions/05.py | 5 +- Solutions/06.py | 18 ++-- Solutions/07.py | 23 ++--- Solutions/08.py | 8 +- Solutions/09.py | 10 +-- Solutions/10.py | 4 +- Solutions/100.py | 15 ++-- Solutions/101.py | 36 ++++---- Solutions/102.py | 19 ++-- Solutions/103.py | 35 ++++---- Solutions/104.py | 19 ++-- Solutions/105.py | 11 ++- Solutions/106.py | 17 ++-- Solutions/107.py | 21 ++--- Solutions/108.py | 13 +-- Solutions/109.py | 7 +- Solutions/11.py | 12 +-- Solutions/110.py | 64 ++++++------- Solutions/111.py | 32 +++---- Solutions/112.py | 51 ++++++----- Solutions/113.py | 7 +- Solutions/114.py | 25 +++--- Solutions/115.py | 40 +++++---- Solutions/116.py | 39 ++++---- Solutions/117.py | 29 +++--- Solutions/118.py | 20 +++-- Solutions/119.py | 13 +-- Solutions/12.py | 10 +-- Solutions/120.py | 13 +-- Solutions/121.py | 24 ++--- Solutions/122.py | 25 ++---- Solutions/123.py | 37 ++++---- Solutions/124.py | 7 +- Solutions/125.py | 31 ++++--- Solutions/126.py | 9 +- Solutions/127.py | 53 +++++------ Solutions/128.py | 35 ++++---- Solutions/129.py | 20 +++-- Solutions/13.py | 31 +++---- Solutions/130.py | 38 +++++--- Solutions/131.py | 36 ++++---- Solutions/132.py | 67 +++++++------- Solutions/133.py | 47 +++++----- Solutions/134.py | 29 +++--- Solutions/135.py | 38 ++++---- Solutions/136.py | 58 +++++------- Solutions/137.py | 31 +++---- Solutions/138.py | 17 ++-- Solutions/139.py | 9 +- Solutions/14.py | 16 ++-- Solutions/140.py | 19 ++-- Solutions/141.py | 27 +++--- Solutions/142.py | 41 +++++---- Solutions/143.py | 26 +++--- Solutions/144.py | 16 ++-- Solutions/145.py | 11 +-- Solutions/146.py | 68 +++++++------- Solutions/147.py | 20 +++-- Solutions/148.py | 19 ++-- Solutions/149.py | 17 ++-- Solutions/15.py | 15 ++-- Solutions/150.py | 8 +- Solutions/151.py | 72 +++++++-------- Solutions/152.py | 12 +-- Solutions/153.py | 17 ++-- Solutions/154.py | 13 +-- Solutions/155.py | 21 ++--- Solutions/156.py | 17 ++-- Solutions/157.py | 13 +-- Solutions/158.py | 51 +++++------ Solutions/159.py | 11 +-- Solutions/16.py | 17 ++-- Solutions/160.py | 54 +++++------ Solutions/161.py | 9 +- Solutions/162.py | 18 ++-- Solutions/163.py | 21 ++--- Solutions/164.py | 9 +- Solutions/165.py | 15 ++-- Solutions/166.py | 15 ++-- Solutions/167.py | 18 ++-- Solutions/168.py | 24 +++-- Solutions/169.py | 92 ++++++++++--------- Solutions/17.py | 32 ++++--- Solutions/170.py | 59 ++++++------ Solutions/171.py | 27 +++--- Solutions/172.py | 12 +-- Solutions/173.py | 21 ++--- Solutions/175.py | 50 ++++++----- Solutions/176.py | 21 ++--- Solutions/177.py | 9 +- Solutions/178.py | 15 ++-- Solutions/179.py | 12 +-- Solutions/18.py | 27 +++--- Solutions/180.py | 11 +-- Solutions/181.py | 23 ++--- Solutions/182.py | 21 ++--- Solutions/184.py | 13 +-- Solutions/185.py | 33 +++---- Solutions/186.py | 21 ++--- Solutions/187.py | 49 +++++----- Solutions/188.py | 8 +- Solutions/189.py | 24 ++--- Solutions/19.py | 33 +++++-- Solutions/190.py | 10 ++- Solutions/191.py | 17 ++-- Solutions/192.py | 17 ++-- Solutions/193.py | 21 ++--- Solutions/194.py | 11 ++- Solutions/195.py | 37 +++----- Solutions/196.py | 27 +++--- Solutions/197.py | 15 ++-- Solutions/198.py | 18 ++-- Solutions/199.py | 39 +++++--- Solutions/20.py | 42 ++++----- Solutions/200.py | 7 +- Solutions/201.py | 29 +++--- Solutions/202.py | 27 +++--- Solutions/203.py | 26 +++--- Solutions/204.py | 46 ++++++---- Solutions/205.py | 18 ++-- Solutions/206.py | 9 +- Solutions/207.py | 19 ++-- Solutions/208.py | 11 +-- Solutions/209.py | 30 +++---- Solutions/21.py | 21 ++--- Solutions/210.py | 32 +++---- Solutions/211.py | 36 ++++---- Solutions/212.py | 11 +-- Solutions/213.py | 26 +++--- Solutions/214.py | 11 +-- Solutions/215.py | 24 ++--- Solutions/216.py | 27 +++--- Solutions/217.py | 21 ++--- Solutions/218.py | 16 ++-- Solutions/219.py | 50 +++++------ Solutions/22.py | 17 ++-- Solutions/220.py | 16 ++-- Solutions/221.py | 22 ++--- Solutions/222.py | 14 +-- Solutions/223.py | 10 +-- Solutions/224.py | 10 +-- Solutions/225.py | 12 +-- Solutions/226.py | 26 +++--- Solutions/227.py | 34 ++++--- Solutions/228.py | 23 +++-- Solutions/229.py | 21 +++-- Solutions/23.py | 86 ++++++++++-------- Solutions/230.py | 19 ++-- Solutions/231.py | 54 ++++++----- Solutions/232.py | 12 +-- Solutions/233.py | 10 ++- Solutions/234.py | 14 +-- Solutions/235.py | 14 +-- Solutions/236.py | 13 +-- Solutions/237.py | 6 +- Solutions/238.py | 8 +- Solutions/239.py | 18 ++-- Solutions/24.py | 76 ++++++++-------- Solutions/240.py | 7 +- Solutions/241.py | 7 +- Solutions/242.py | 11 +-- Solutions/243.py | 6 +- Solutions/244.py | 5 +- Solutions/245.py | 10 +-- Solutions/246.py | 31 +++++-- Solutions/247.py | 8 +- Solutions/248.py | 6 +- Solutions/249.py | 8 +- Solutions/25.py | 21 ++--- Solutions/250.py | 10 ++- Solutions/251.py | 6 +- Solutions/252.py | 4 +- Solutions/253.py | 4 +- Solutions/254.py | 24 ++--- Solutions/255.py | 12 +-- Solutions/256.py | 6 +- Solutions/257.py | 6 +- Solutions/258.py | 8 +- Solutions/259.py | 9 +- Solutions/26.py | 13 +-- Solutions/260.py | 9 +- Solutions/261.py | 16 ++-- Solutions/262.py | 70 ++++++++------- Solutions/27.py | 21 +++-- Solutions/28.py | 75 ++++++++-------- Solutions/29.py | 16 ++-- Solutions/30.py | 11 +-- Solutions/31.py | 22 ++--- Solutions/32.py | 11 ++- Solutions/33.py | 22 ++--- Solutions/34.py | 25 +++--- Solutions/35.py | 17 ++-- Solutions/36.py | 30 ++++--- Solutions/37.py | 11 +-- Solutions/38.py | 16 ++-- Solutions/39.py | 120 +++++++++++++++---------- Solutions/40.py | 31 +++---- Solutions/41.py | 30 ++++--- Solutions/42.py | 19 ++-- Solutions/43.py | 40 +++++---- Solutions/44.py | 19 ++-- Solutions/45.py | 13 +-- Solutions/46.py | 16 ++-- Solutions/47.py | 17 ++-- Solutions/48.py | 27 +++--- Solutions/49.py | 25 +++--- Solutions/50.py | 35 +++++--- Solutions/51.py | 7 +- Solutions/52.py | 22 ++--- Solutions/53.py | 20 +++-- Solutions/54.py | 46 +++++----- Solutions/55.py | 21 ++--- Solutions/56.py | 17 ++-- Solutions/57.py | 19 ++-- Solutions/58.py | 63 ++++++------- Solutions/59.py | 56 ++++++------ Solutions/60.py | 29 +++--- Solutions/61.py | 15 ++-- Solutions/62.py | 13 +-- Solutions/63.py | 31 ++++--- Solutions/64.py | 44 ++++----- Solutions/65.py | 55 +++++------- Solutions/66.py | 18 ++-- Solutions/67.py | 28 +++--- Solutions/68.py | 37 ++++---- Solutions/69.py | 33 +++---- Solutions/70.py | 39 ++++---- Solutions/71.py | 12 +-- Solutions/72.py | 11 +-- Solutions/73.py | 13 +-- Solutions/74.py | 17 ++-- Solutions/75.py | 13 +-- Solutions/76.py | 13 +-- Solutions/77.py | 13 +-- Solutions/78.py | 13 +-- Solutions/79.py | 13 +-- Solutions/80.py | 36 ++++---- Solutions/81.py | 19 ++-- Solutions/82/82.py | 14 +-- Solutions/83.py | 18 ++-- Solutions/84.py | 49 +++++----- Solutions/85.py | 9 +- Solutions/86.py | 25 +++--- Solutions/87.py | 60 +++++++------ Solutions/88.py | 17 ++-- Solutions/89.py | 36 ++++---- Solutions/90.py | 17 ++-- Solutions/91.py | 10 +-- Solutions/92.py | 64 ++++++------- Solutions/93.py | 42 +++++---- Solutions/94.py | 25 ++++-- Solutions/95.py | 27 +++--- Solutions/96.py | 25 +++--- Solutions/97.py | 89 +++++++++--------- Solutions/98.py | 52 +++++------ Solutions/99.py | 25 +++--- Solutions/DataStructures/Graph.py | 12 +-- Solutions/DataStructures/LinkedList.py | 10 +-- Solutions/DataStructures/Queue.py | 4 +- Solutions/DataStructures/Stack.py | 8 +- Solutions/DataStructures/Tree.py | 14 +-- Solutions/DataStructures/Trie.py | 10 +-- 266 files changed, 3384 insertions(+), 2989 deletions(-) diff --git a/Solutions/01.py b/Solutions/01.py index 72b7d16..72ed948 100644 --- a/Solutions/01.py +++ b/Solutions/01.py @@ -1,11 +1,11 @@ -''' +""" Problem: Given a list of numbers, return whether any two sums to k. For example, given [10, 15, 3, 7] and k of 17, return true since 10 + 7 is 17. Bonus: Can you do this in one pass? -''' +""" from typing import List @@ -26,9 +26,9 @@ def check_target_sum(arr: List[int], target: int) -> bool: print(check_target_sum([10, 15, 3, 4], 17)) -''' +""" SPECS: TIME COMPLEXITY: O(n) SPACE COMPLEXITY: O(n) -''' +""" diff --git a/Solutions/02.py b/Solutions/02.py index b62c8b2..c31d12a 100644 --- a/Solutions/02.py +++ b/Solutions/02.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of integers, return a new array such that each element at index i of the @@ -9,7 +9,7 @@ [2, 3, 6]. Follow-up: what if you can't use division? -''' +""" from typing import List @@ -36,9 +36,9 @@ def product_of_arr_except_ith_elem(arr: List[int]) -> int: print(product_of_arr_except_ith_elem([3, 2, 1])) -''' +""" SPECS: TIME COMPLEXITY: O(n) SPACE COMPLEXITY: O(n) -''' +""" diff --git a/Solutions/03.py b/Solutions/03.py index 5e049c7..2b7bf9c 100644 --- a/Solutions/03.py +++ b/Solutions/03.py @@ -1,8 +1,8 @@ -''' +""" Problem: Write a program to serialize a tree into a string and deserialize a string into a tree. -''' +""" from typing import List @@ -21,10 +21,10 @@ def serialize_helper(self) -> str: return f"'{self.val}','None',{self.left.serialize_helper()}" elif self.left is not None and self.right is not None: return ( - f"'{self.val}'," + - f"{self.left.serialize_helper()}," + - f"{self.right.serialize_helper()}" - ) + f"'{self.val}'," + + f"{self.left.serialize_helper()}," + + f"{self.right.serialize_helper()}" + ) # Function to serialize the tree @@ -33,8 +33,8 @@ def serialize(self) -> str: # adding serialization fctions to node and tree -setattr(Node, 'serialize_helper', serialize_helper) -setattr(BinaryTree, 'serialize', serialize) +setattr(Node, "serialize_helper", serialize_helper) +setattr(BinaryTree, "serialize", serialize) # Function to deserialize the string @@ -42,13 +42,13 @@ def deserialize_helper(node: Node, data: List[str]) -> Node: # data is a queue containing the data as a prefix notation can be easily decoded # using a queue left = data.pop(0).strip("'") - if left != 'None': + if left != "None": # if the left child exists, its added to the tree and deserialize_helper called node.left = Node(left) node.left = deserialize_helper(node.left, data) right = data.pop(0).strip("'") - if right != 'None': + if right != "None": # if the right child exists, its added to the tree and deserialize_helper # called node.right = Node(right) @@ -60,7 +60,7 @@ def deserialize_helper(node: Node, data: List[str]) -> Node: def deserialize(string: str) -> BinaryTree: # the string is considered to have the same format as the binary tree serialization # eg: data is padded with single quotes (') and comma (,) is used as a delimiter - data = string.split(',') + data = string.split(",") tree = BinaryTree() tree.root = Node(data.pop(0).strip("'")) deserialize_helper(tree.root, data) @@ -78,12 +78,12 @@ def deserialize(string: str) -> BinaryTree: generated_tree = deserialize( "'root','left','left.left','None','None','None','right','None','None'" - ) + ) print(generated_tree.serialize()) -''' +""" SPECS: SERIALIZE: (n = Number of Nodes) @@ -93,4 +93,4 @@ def deserialize(string: str) -> BinaryTree: DESERIALIZE: (n = Number of Characters in the String) TIME COMPLEXITY: O(n) SPACE COMPLEXITY: O(n) -''' +""" diff --git a/Solutions/04.py b/Solutions/04.py index c09b670..bb46205 100644 --- a/Solutions/04.py +++ b/Solutions/04.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of integers, find the first missing positive integer in linear time and @@ -8,7 +8,7 @@ For example, the input [3, 4, -1, 1] should give 2. The input [1, 2, 0] should give 3. You can modify the input array in-place. -''' +""" from typing import List @@ -40,9 +40,9 @@ def first_missing_positive_integer(arr: List[int]) -> int: print(first_missing_positive_integer([-1, -2])) -''' +""" SPECS: TIME COMPLEXITY: O(n) SPACE COMPLEXITY: O(1) -''' +""" diff --git a/Solutions/05.py b/Solutions/05.py index bbf8cde..a3eccfa 100644 --- a/Solutions/05.py +++ b/Solutions/05.py @@ -1,4 +1,4 @@ -''' +""" Problem: cons(a, b) constructs a pair, and car(pair) and cdr(pair) returns the first and last @@ -11,7 +11,7 @@ def cons(a, b): def pair(f): return f(a, b) return pair -''' +""" from typing import Callable @@ -20,6 +20,7 @@ def pair(f): def cons(a, b): def pair(f): return f(a, b) + return pair diff --git a/Solutions/06.py b/Solutions/06.py index 645a1df..5adb586 100644 --- a/Solutions/06.py +++ b/Solutions/06.py @@ -1,4 +1,4 @@ -''' +""" Problem: An XOR linked list is a more memory efficient doubly linked list. Instead of each node @@ -9,10 +9,10 @@ If using a language that has no pointers (such as Python), you can assume you have access to get_pointer and dereference_pointer functions that converts between nodes and memory addresses. -''' +""" -# Solution copied from: +# Solution copied from: # https://github.com/r1cc4rdo/daily_coding_problem/blob/master/problems/06 @@ -54,15 +54,16 @@ def head(self) -> Tuple[int, int, XORLinkedListNode]: def add(self, val: int) -> None: current_node_index, previous_node_index, current_node = self.head() - while True: + while True: # walk down the list until the end is found next_node_index = current_node.next_node(previous_node_index) if next_node_index == -1: # the end is reached break previous_node_index, current_node_index = ( - current_node_index, next_node_index - ) + current_node_index, + next_node_index, + ) current_node = self.memory[next_node_index] # allocation new_node_index = len(self.memory) @@ -73,8 +74,9 @@ def get(self, index: int) -> int: current_index, previous_index, current_node = self.head() for _ in range(index + 1): previous_index, current_index = ( - current_index, current_node.next_node(previous_index) - ) + current_index, + current_node.next_node(previous_index), + ) current_node = self.memory[current_index] return current_node.val diff --git a/Solutions/07.py b/Solutions/07.py index c85d55f..3f90471 100644 --- a/Solutions/07.py +++ b/Solutions/07.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given the mapping a = 1, b = 2, ... z = 26, and an encoded message, count the number of @@ -8,7 +8,8 @@ and 'ak'. You can assume that the messages are decodable. For example, '001' is not allowed. -''' +""" + def count_decoding(digits: str) -> int: len_digits = len(digits) @@ -21,26 +22,26 @@ def count_decoding(digits: str) -> int: for i in range(2, len_digits + 1): count[i] = 0 # if the last digit is not 0, then last digit must add to the number of words - if digits[i - 1] > '0': + if digits[i - 1] > "0": count[i] = count[i - 1] # if the number formed by the last 2 digits is less than 26, its a valid # character - if digits[i - 2] == '1' or (digits[i - 2] == '2' and digits[i - 1] < '7'): + if digits[i - 2] == "1" or (digits[i - 2] == "2" and digits[i - 1] < "7"): count[i] += count[i - 2] return count[len_digits] if __name__ == "__main__": - print(count_decoding('81')) - print(count_decoding('11')) - print(count_decoding('111')) - print(count_decoding('1311')) - print(count_decoding('1111')) + print(count_decoding("81")) + print(count_decoding("11")) + print(count_decoding("111")) + print(count_decoding("1311")) + print(count_decoding("1111")) -''' +""" SPECS: TIME COMPLEXITY: O(n) SPACE COMPLEXITY: O(n) -''' +""" diff --git a/Solutions/08.py b/Solutions/08.py index e204b5f..106ada7 100644 --- a/Solutions/08.py +++ b/Solutions/08.py @@ -1,4 +1,4 @@ -''' +""" Problem: A unival tree (which stands for "universal value") is a tree where all nodes under it @@ -15,7 +15,7 @@ 1 0 / \ 1 1 -''' +""" from typing import Tuple @@ -80,9 +80,9 @@ def num_universal(tree: BinaryTree) -> int: print(num_universal(tree)) -''' +""" SPECS: TIME COMPLEXITY: O(n) SPACE COMPLEXITY: O(n) [call stack included] -''' +""" diff --git a/Solutions/09.py b/Solutions/09.py index 145d34d..cea1c7a 100644 --- a/Solutions/09.py +++ b/Solutions/09.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of integers, write a function that returns the largest sum of non-adjacent @@ -6,7 +6,7 @@ For example, [2, 4, 6, 8] should return 12, since we pick 4 and 8. [5, 1, 1, 5] should return 10, since we pick 5 and 5. -''' +""" from typing import List @@ -18,7 +18,7 @@ def max_nonadjacent_sum(arr: List[int]) -> int: # updating including and excluding temp = including including = max(excluding + elem, elem) - excluding = max(temp, including-elem) + excluding = max(temp, including - elem) return max(including, excluding) @@ -29,9 +29,9 @@ def max_nonadjacent_sum(arr: List[int]) -> int: print(max_nonadjacent_sum([5, 5, 10, 100, 10, 5])) -''' +""" SPECS: TIME COMPLEXITY: O(n) SPACE COMPLEXITY: O(1) -''' +""" diff --git a/Solutions/10.py b/Solutions/10.py index e141823..55ebc02 100644 --- a/Solutions/10.py +++ b/Solutions/10.py @@ -1,9 +1,9 @@ -''' +""" Problem: Implement a job scheduler which takes in a function f and an integer n, and calls f after n milliseconds. -''' +""" from time import sleep from typing import Callable diff --git a/Solutions/100.py b/Solutions/100.py index d9c1f12..e9c481f 100644 --- a/Solutions/100.py +++ b/Solutions/100.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are in an infinite 2D grid where you can move in any of the 8 directions: @@ -18,7 +18,7 @@ Input = [(0, 0), (1, 1), (1, 2)] Output = 2 (It takes 1 step to move from (0, 0) to (1, 1). It takes one more step to move from (1, 1) to (1, 2)) -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_min_steps(sequence): @@ -26,9 +26,9 @@ def get_min_steps(sequence): length = len(sequence) # returning 0 if there is 1 or no element - if (length in [0, 1]): + if length in [0, 1]: return 0 - + # getting the current position curr = sequence[0] # storing the total distance covered @@ -42,16 +42,17 @@ def get_min_steps(sequence): y, x = next_pos # increasing dist by the maximum of the x and y distance between current and next position - dist += max((abs(y-i)), abs(x-j)) + dist += max((abs(y - i)), abs(x - j)) # updating current position to the next position curr = next_pos - + return dist + # DRIVER CODE print(get_min_steps([])) print(get_min_steps([(0, 0)])) print(get_min_steps([(0, 0), (1, 1), (1, 2)])) print(get_min_steps([(0, 0), (1, 1), (1, 2), (3, 4)])) -print(get_min_steps([(0, 0), (1, 1), (1, 2), (3, 6)])) \ No newline at end of file +print(get_min_steps([(0, 0), (1, 1), (1, 2), (3, 6)])) diff --git a/Solutions/101.py b/Solutions/101.py index 007c0c5..dbf90fd 100644 --- a/Solutions/101.py +++ b/Solutions/101.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an even number (greater than 2), return two prime numbers whose sum will be equal to the given number. @@ -12,41 +12,43 @@ (If [a, b] is one solution with a <= b, and [c, d] is another solution with c <= d, then [a, b] < [c, d] if a < c or a==c and b < d) -''' +""" # function to check if a number is prime def prime(num): # if the number is 2 or 3, True is returned - if (num == 2 or num == 3): + if num == 2 or num == 3: return True # looping over all its potential divisors for i in range(2, int(num ** 0.5) + 1): # if it is divisble by any number False is returned - if (num % i == 0): + if num % i == 0: return False # if no divisor is found, True is returned return True + # FUNCTION TO PERFORM THE OPERATION def num_sum(n): # checking if n-2 is prime - if (n > 2 and prime(n-2)): - return (2, n-2) + if n > 2 and prime(n - 2): + return (2, n - 2) # checking if n-3 is prime - if (n > 3 and prime(n-3)): - return (3, n-3) - + if n > 3 and prime(n - 3): + return (3, n - 3) + # looping over all possible prime numbers [using formula all prime numbers are of the form (6n + 1) or (6n - 1)] - for i in range(6, n//2, 6): + for i in range(6, n // 2, 6): # checking if (6n - 1) satisfies the result - if (prime(i-1)): - if (prime(n-i+1)): - return ((i-1), (n-i+1)) + if prime(i - 1): + if prime(n - i + 1): + return ((i - 1), (n - i + 1)) # checking if (6n + 1) satisfies the result - elif (prime(i+1)): - if (prime(n-i-1)): - return ((i+1), (n-i-1)) + elif prime(i + 1): + if prime(n - i - 1): + return ((i + 1), (n - i - 1)) + # DRIVER CODE inp = 4 @@ -59,4 +61,4 @@ def num_sum(n): inp = 100 res = num_sum(inp) -print(f"{inp} = {res[0]} + {res[1]}") \ No newline at end of file +print(f"{inp} = {res[0]} + {res[1]}") diff --git a/Solutions/102.py b/Solutions/102.py index 02f66fa..d46b3eb 100644 --- a/Solutions/102.py +++ b/Solutions/102.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of integers and a number K, return which contiguous elements of the list sum to K. @@ -7,7 +7,7 @@ Input = [1, 2, 3, 4, 5], 9 Output = [2, 3, 4] -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_part(arr, k): @@ -21,25 +21,26 @@ def get_part(arr, k): iteration = 0 # using a moving window to converge to the final answer - while (iteration < length): + while iteration < length: # if the window has been found, we return the part of the list - if (total_sum == k): - return arr[start : end] + if total_sum == k: + return arr[start:end] # if the total_sum exceeds the target sum, we remove the starting element from the window - elif (total_sum > k): + elif total_sum > k: total_sum -= arr[start] start += 1 - + # if the total_sum is smaller than the target sum, we add the next element to the window else: total_sum += arr[iteration] end = iteration + 1 iteration += 1 - + # returning None if the target sum cannot be achieved return None + # DRIVER CODE print(get_part([1, 2, 3, 4, 5], 0)) print(get_part([1, 2, 3, 4, 5], 1)) @@ -48,4 +49,4 @@ def get_part(arr, k): print(get_part([5, 4, 3, 4, 5], 11)) print(get_part([1, 2, 3, 4, 5], 9)) print(get_part([1, 2, 3, 4, 5], 3)) -print(get_part([1, 2, 3, 4, 5], 300)) \ No newline at end of file +print(get_part([1, 2, 3, 4, 5], 300)) diff --git a/Solutions/103.py b/Solutions/103.py index f9e3fa2..55f983b 100644 --- a/Solutions/103.py +++ b/Solutions/103.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string and a set of characters, return the shortest substring containing all the characters in the set. @@ -8,7 +8,7 @@ Input = "figehaeci", {a, e, i} Output = "aeci" -''' +""" # FUNCTION TO PERFORM THE OPERATION def shortest_substring_with_all_characters(string, characters): @@ -18,7 +18,7 @@ def shortest_substring_with_all_characters(string, characters): ind_queue = [] # curr_seen stores the number of required characters in the part under consideration curr_seen = set() - + # num_char stores the number of characters to consider (length of the passed character set) num_char = len(characters) # result is the final result @@ -28,33 +28,34 @@ def shortest_substring_with_all_characters(string, characters): for i in range(len(string)): # if the current character is in the required characters, its added to curr_queue # the index is added to ind_queue and the character to the curr_seen set - if (string[i] in characters): + if string[i] in characters: curr_queue.append(string[i]) ind_queue.append(i) curr_seen.add(string[i]) - + # getting the required shift (to shorten the substring) shift = 0 - for k in range(len(curr_queue)//2): - if (curr_queue[k] == curr_queue[-k-1]): + for k in range(len(curr_queue) // 2): + if curr_queue[k] == curr_queue[-k - 1]: shift += 1 # truncating the queues curr_queue = curr_queue[shift:] ind_queue = ind_queue[shift:] # if all the necessary characters have been found - if (len(curr_seen) == num_char): + if len(curr_seen) == num_char: # if the result is None or the length of the result is larger than the one constructed, its updated - if ((not result) or (len(result) > (ind_queue[-1] - ind_queue[0] + 1))): - result = string[ind_queue[0]:ind_queue[-1]+1] + if (not result) or (len(result) > (ind_queue[-1] - ind_queue[0] + 1)): + result = string[ind_queue[0] : ind_queue[-1] + 1] return result + # DRIVER CODE -print(shortest_substring_with_all_characters("abcdedbc", {'g', 'f'})) -print(shortest_substring_with_all_characters("abccbbbccbcb", {'a', 'b', 'c'})) -print(shortest_substring_with_all_characters("figehaeci", {'a', 'e', 'i'})) -print(shortest_substring_with_all_characters("abcdedbc", {'d', 'b', 'b'})) -print(shortest_substring_with_all_characters("abcdedbc", {'b', 'c'})) -print(shortest_substring_with_all_characters("abcdecdb", {'b', 'c'})) -print(shortest_substring_with_all_characters("abcdecdb", {'b', 'c', 'e'})) \ No newline at end of file +print(shortest_substring_with_all_characters("abcdedbc", {"g", "f"})) +print(shortest_substring_with_all_characters("abccbbbccbcb", {"a", "b", "c"})) +print(shortest_substring_with_all_characters("figehaeci", {"a", "e", "i"})) +print(shortest_substring_with_all_characters("abcdedbc", {"d", "b", "b"})) +print(shortest_substring_with_all_characters("abcdedbc", {"b", "c"})) +print(shortest_substring_with_all_characters("abcdecdb", {"b", "c"})) +print(shortest_substring_with_all_characters("abcdecdb", {"b", "c", "e"})) diff --git a/Solutions/104.py b/Solutions/104.py index d84c2b0..af16191 100644 --- a/Solutions/104.py +++ b/Solutions/104.py @@ -1,4 +1,4 @@ -''' +""" Problem: Determine whether a doubly linked list is a palindrome. What if it’s singly linked? @@ -10,7 +10,7 @@ Input = 1 -> 4 Output = false -''' +""" # local import from the DataStructures module from DataStructures.LinkedList import Linked_list @@ -18,13 +18,13 @@ # FUNCTION TO PERFORM THE OPERATION def palindrome(self): # if the linked list is empty, False is returned - if (self.head == None): + if self.head == None: return False - + # if the list contains only 1 element, True is returned - elif (self.rear == self.head): + elif self.rear == self.head: return True - + else: # pos1 stores the addresses for comparison from the beginning pos1 = self.head @@ -34,7 +34,7 @@ def palindrome(self): # comparing all the values from the beginning to the end for i in range((self.length + 1) // 2): # if there's a mismatch, False is returned - if (pos1.val != pos2.val): + if pos1.val != pos2.val: return False # updating the end pointer (pos2) [operation done for Single Linked List, so its of O(n^2), for Double Linked List, it would be O(n)] @@ -48,8 +48,9 @@ def palindrome(self): return True + # adding the function to the Linked List class -setattr(Linked_list, 'palindrome', palindrome) +setattr(Linked_list, "palindrome", palindrome) # DRIVER CODE LL = Linked_list() @@ -77,4 +78,4 @@ def palindrome(self): LL = Linked_list() -print("Palindrome: {}\t\tList: {}".format(LL.palindrome(), LL)) \ No newline at end of file +print("Palindrome: {}\t\tList: {}".format(LL.palindrome(), LL)) diff --git a/Solutions/105.py b/Solutions/105.py index 229478a..7841ec4 100644 --- a/Solutions/105.py +++ b/Solutions/105.py @@ -1,9 +1,9 @@ -''' +""" Problem: Given a function f, and N return a debounced f of N milliseconds. That is, as long as the debounced f continues to be invoked, f itself will not be called for N milliseconds. -''' +""" # import from the time module from time import sleep @@ -24,20 +24,23 @@ def wrapped(*args, **kwargs): # calling the function return f(*args, **kwargs) + # returning the wrapped function return wrapped + # returning the decorate function return decorate # FUNCTION TO PERFORM THE OPERATION -@debounce(3000) # decorator function to implement debouncing +@debounce(3000) # decorator function to implement debouncing # ordinary addition function def add_nums(x, y): return x + y + # DRIVER CODE print(add_nums(1, 1)) print(add_nums(1, 2)) print(add_nums(1, 3)) -print(add_nums(1, 4)) \ No newline at end of file +print(add_nums(1, 4)) diff --git a/Solutions/106.py b/Solutions/106.py index ef0e876..a5f177c 100644 --- a/Solutions/106.py +++ b/Solutions/106.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an integer list where each number represents the number of hops you can make. @@ -11,7 +11,7 @@ Input = [1, 1, 0, 1] Output = false -''' +""" # FUNCTION TO PERFORM THE OPERATION def can_reach_end(arr): @@ -19,22 +19,23 @@ def can_reach_end(arr): pos = 0 # length stores the length of the list length = len(arr) - + # looping till the pointer value is less than the length of the list - while (pos < length): + while pos < length: # if we reach the last position, True is returned - if (pos == length-1): + if pos == length - 1: return True # if the value in the list at the current position is 0, False is retuened (we cannot move any more) - elif (arr[pos] == 0): + elif arr[pos] == 0: return False # getting the next position pos += arr[pos] - + # if we surpass the last index, False is returned return False + # DRIVER CODE print(can_reach_end([2, 0, 1, 0])) print(can_reach_end([1, 1, 0, 1])) -print(can_reach_end([1, 1, 10, 1])) \ No newline at end of file +print(can_reach_end([1, 1, 10, 1])) diff --git a/Solutions/107.py b/Solutions/107.py index d64c87e..7f2869e 100644 --- a/Solutions/107.py +++ b/Solutions/107.py @@ -1,4 +1,4 @@ -''' +""" Problem: Print the nodes in a binary tree level-wise. @@ -11,7 +11,7 @@ / \ 4 5 Output = 1, 2, 3, 4, 5 -''' +""" # local import from the DataStructures from DataStructures.Tree import Binary_Tree, Node @@ -24,25 +24,26 @@ def lvl_wise_nodes(self): ans = [] # looping till all nodes are processed - while (queue != []): + while queue != []: # getting the current node pos = queue.pop(0) # if the node has a left child, its added to the queue for processing - if (pos.left != None): + if pos.left != None: queue.append(pos.left) - + # if the node has a right child, its added to the queue for processing - if (pos.right != None): + if pos.right != None: queue.append(pos.right) - + # adding the current node's value to the ans ans.append(pos.val) - + return ans + # adding the function to the Binary Tree class -setattr(Binary_Tree, 'lvl_wise_nodes', lvl_wise_nodes) +setattr(Binary_Tree, "lvl_wise_nodes", lvl_wise_nodes) # DRIVER CODE tree = Binary_Tree(1) @@ -52,4 +53,4 @@ def lvl_wise_nodes(self): tree.root.right.right = Node(5) print(f"Tree: {tree}") -print(f"Level wise result: {tree.lvl_wise_nodes()}") \ No newline at end of file +print(f"Level wise result: {tree.lvl_wise_nodes()}") diff --git a/Solutions/108.py b/Solutions/108.py index 22b4229..2dff44a 100644 --- a/Solutions/108.py +++ b/Solutions/108.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given two strings A and B, return whether or not A can be shifted some number of times to get B. @@ -10,17 +10,18 @@ Input = abc, acb Output = false -''' +""" # FUNCTION TO PERFORM THE OPERATION def can_shift(str_A, str_B): # if the strings are not empty and have equal length, the returned value is whether B can be found in twice A (due to shifting) - if ((str_A and str_B) and (len(str_A) == len(str_B))): - return (str_B in (str_A * 2)) - + if (str_A and str_B) and (len(str_A) == len(str_B)): + return str_B in (str_A * 2) + # otherwise False is returned return False + # DRIVER CODE print(can_shift("abcde", "cdeab")) -print(can_shift("abc", "acb")) \ No newline at end of file +print(can_shift("abc", "acb")) diff --git a/Solutions/109.py b/Solutions/109.py index 25bc330..932671c 100644 --- a/Solutions/109.py +++ b/Solutions/109.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an unsigned 8-bit integer, swap its even and odd bits. @@ -12,7 +12,7 @@ Input = 11100010 Output = 11010001 -''' +""" # FUNCTION TO PERFORM THE OPERATION def swap_bits(num): @@ -24,9 +24,10 @@ def swap_bits(num): # (using the mask to get the digits at odd position and left shifting) BITWISE-OR (using the mask to get the digits at even position and right shifting) return ((num & filter_mask) << 1) | ((num & (filter_mask << 1)) >> 1) + # DRIVER CODE print("Swapped:", bin(swap_bits(0))) print("Swapped:", bin(swap_bits(255))) print("Swapped:", bin(swap_bits(210))) print("Swapped:", bin(swap_bits(170))) -print("Swapped:", bin(swap_bits(226))) \ No newline at end of file +print("Swapped:", bin(swap_bits(226))) diff --git a/Solutions/11.py b/Solutions/11.py index ae8804e..b620a8b 100644 --- a/Solutions/11.py +++ b/Solutions/11.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement an autocomplete system. That is, given a query string s and a set of all @@ -9,7 +9,7 @@ Hint: Try preprocessing the dictionary into a more efficient data structure to speed up queries. -''' +""" from typing import List @@ -18,7 +18,7 @@ def get_suggestion(word_list: List[str], prefix: str) -> List[str]: - # using tree data structure to get the suggestions (for deatils, check + # using tree data structure to get the suggestions (for deatils, check # ./DataStructres/Trie) trie = Trie() trie.add_words(word_list) @@ -28,13 +28,13 @@ def get_suggestion(word_list: List[str], prefix: str) -> List[str]: if __name__ == "__main__": - print(get_suggestion(['deer', 'dog', 'deal'], 'de')) + print(get_suggestion(["deer", "dog", "deal"], "de")) -''' +""" SPECS: TIME COMPLEXITY: O(n) SPACE COMPLEXITY: O(n) [n = total number of characters (all words)] -''' +""" diff --git a/Solutions/110.py b/Solutions/110.py index db14304..e0bc777 100644 --- a/Solutions/110.py +++ b/Solutions/110.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a binary tree, return all paths from the root to leaves. @@ -10,46 +10,48 @@ 2 3 / \ 4 5 -Output = [[1, 2], [1, 3, 4], [1, 3, 5]]''' +Output = [[1, 2], [1, 3, 4], [1, 3, 5]]""" # local import from the DataStructures module from DataStructures.Tree import Binary_Tree, Node # helper function to do the heavy-lifting (part of Node class) def get_paths_helper(self, res, temp): - # if a leaf node is reached - if (not self.left and not self.right): - # the leaf's value is added to temp - temp.append(self.val) - # a deep copy of temp is added to res - res.append(list(temp)) - # the value of the leaf is poped from temp - temp.pop() - # if the node is not a leaf - else: - # the node's value is added to temp - temp.append(self.val) - # if the node has a left child, the function is recursively called on left child - if (self.left): - self.left.get_paths_helper(res, temp) - # if the node has a right child, the function is recursively called on right child - if (self.right): - self.right.get_paths_helper(res, temp) - # the node's value is removed from temp - temp.pop() + # if a leaf node is reached + if not self.left and not self.right: + # the leaf's value is added to temp + temp.append(self.val) + # a deep copy of temp is added to res + res.append(list(temp)) + # the value of the leaf is poped from temp + temp.pop() + # if the node is not a leaf + else: + # the node's value is added to temp + temp.append(self.val) + # if the node has a left child, the function is recursively called on left child + if self.left: + self.left.get_paths_helper(res, temp) + # if the node has a right child, the function is recursively called on right child + if self.right: + self.right.get_paths_helper(res, temp) + # the node's value is removed from temp + temp.pop() + # FUNCTION TO PERFORM THE OPERATION def get_paths(self): - # res stores the values from root to leaves - res = [] - # calling the helper function on the root - self.root.get_paths_helper(res, []) - # returning res - return res + # res stores the values from root to leaves + res = [] + # calling the helper function on the root + self.root.get_paths_helper(res, []) + # returning res + return res + # adding the necessary functions to their respective classes -setattr(Node, 'get_paths_helper', get_paths_helper) -setattr(Binary_Tree, 'get_paths', get_paths) +setattr(Node, "get_paths_helper", get_paths_helper) +setattr(Binary_Tree, "get_paths", get_paths) # DRIVER CODE tree = Binary_Tree(1) @@ -59,4 +61,4 @@ def get_paths(self): tree.root.right.right = Node(5) print(tree) -print(tree.get_paths()) \ No newline at end of file +print(tree.get_paths()) diff --git a/Solutions/111.py b/Solutions/111.py index bd4b2e8..85cd87f 100644 --- a/Solutions/111.py +++ b/Solutions/111.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a word W and a string S, find all starting indices in S which are anagrams of W. @@ -7,20 +7,21 @@ Input = "ab", "abxaba" Output = [0, 3, 4] -''' +""" # helper to break the string into a dictionary of characters and number of occourances def break_char(string): d = {} for i in string: - if (i in d): + if i in d: d[i] += 1 else: d[i] = 1 - + return d + # FUNCTION TO PERFORM THE OPERATION def get_word_start_loc(word, string): # getting the length of the word @@ -37,31 +38,31 @@ def get_word_start_loc(word, string): res = [] # if the word is longer than the string, no anagram is possible - if ((word_len > str_len) or (word_len == 0)): + if (word_len > str_len) or (word_len == 0): return [] - + # looping till we reach the end of the string - while (curr < str_len): + while curr < str_len: # looping till we reach the end of the string from current position # [NOTE: the algo is O(n) evene though it has a nested loop] for i in range(curr, str_len): # if a character mismatch occours, we break out (incrementing curr + reseting needed) - if (string[i] not in needed): + if string[i] not in needed: curr = i needed = dict(needed_master) break - + # if the charater is in needed - elif (string[i] in needed): + elif string[i] in needed: # the character count is reduced by 1 needed[string[i]] -= 1 # if the character count reaches 0 - if (needed[string[i]] == 0): + if needed[string[i]] == 0: # we delete the character from needed del needed[string[i]] # if needed is empty - if (needed == {}): + if needed == {}: # we add the current position to res res.append(curr) # setting curr to the current position @@ -69,12 +70,13 @@ def get_word_start_loc(word, string): # reseting needed needed = dict(needed_master) break - + # incrementing curr curr += 1 - + return res + # DRIVER CODE print(get_word_start_loc("ab", "abxaba")) -print(get_word_start_loc("tac", "cataract")) \ No newline at end of file +print(get_word_start_loc("tac", "cataract")) diff --git a/Solutions/112.py b/Solutions/112.py index aed658c..1c91f0f 100644 --- a/Solutions/112.py +++ b/Solutions/112.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. @@ -6,49 +6,51 @@ According to the definition of LCA on Wikipedia: "The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants. (where we allow a node to be a descendant of itself)" -''' +""" # Node class for the nodes of the tree -class Node(): +class Node: # initialization def __init__(self, val, left=None, right=None, parent=None): self.val = val self.left = left self.right = right self.parent = parent - + # string function def __str__(self): return self.to_str() # equality function def __eq__(self, other): - return (self is other) - + return self is other + # helper function to convert the tree into a string def to_str(self): - if (self.right == None and self.left == None): + if self.right == None and self.left == None: return f"('{self.val}')" - elif (self.left != None and self.right == None): + elif self.left != None and self.right == None: return f"({self.left.to_str()}, '{self.val}', None)" - elif (self.left != None and self.right != None): + elif self.left != None and self.right != None: return f"({self.left.to_str()}, '{self.val}', {self.right.to_str()})" - elif (self.left == None and self.right != None): + elif self.left == None and self.right != None: return f"(None, '{self.val}', {self.right.to_str()})" + # Binary Tree class -class Binary_Tree(): +class Binary_Tree: # initialization def __init__(self, val=None): - if (val != None): + if val != None: self.root = Node(val) else: self.root = None - + # string function def __str__(self): return str(self.root) + # FUNCTION TO PERFROM THE OPERATION def get_lca(node1, node2): # depth1 and depth2 stores the depth at which node1 and node2 are located @@ -59,10 +61,10 @@ def get_lca(node1, node2): pos = node1 # traversing to the root and getting the depth - while (pos.parent): + while pos.parent: pos = pos.parent depth1 += 1 - + # storing the root in temp temp = pos @@ -70,35 +72,36 @@ def get_lca(node1, node2): pos = node2 # traversing to the root and getting the depth - while (pos.parent): + while pos.parent: pos = pos.parent depth2 += 1 - + # if the nodes reside in different trees, None is returned if not (temp == pos): return None - + # pointers to get the current poistion during the traversal for each node pos1 = node1 pos2 = node2 # moving pos1 to the correct position for comparision - if (depth1 > depth2): + if depth1 > depth2: for _ in range(depth1 - depth2): pos1 = pos1.parent # moving pos2 to the correct position for comparision else: for _ in range(depth2 - depth1): pos2 = pos2.parent - + # comparing the values of the pointers to find the correct position - while (pos1): - if (pos1 == pos2): + while pos1: + if pos1 == pos2: return pos1.val - + pos1 = pos1.parent pos2 = pos2.parent + # DRIVER CODE tree = Binary_Tree() a = Node(1) @@ -123,4 +126,4 @@ def get_lca(node1, node2): print(get_lca(a, g)) print(get_lca(d, g)) print(get_lca(a, c)) -print(get_lca(e, b)) \ No newline at end of file +print(get_lca(e, b)) diff --git a/Solutions/113.py b/Solutions/113.py index 387056c..2b0a3ab 100644 --- a/Solutions/113.py +++ b/Solutions/113.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string of words delimited by spaces, reverse the words in string. @@ -8,12 +8,13 @@ Input = "hello world here" Output = "here world hello" -''' +""" # FUNCTION TO PERFORM THE OPERATION def rev(string): # spilting the string into the words, reversing the list of words and joining the words with spaces return " ".join(string.split()[::-1]) + # DRIVER CODE -print(rev("hello world here")) \ No newline at end of file +print(rev("hello world here")) diff --git a/Solutions/114.py b/Solutions/114.py index dda05ec..d25f980 100644 --- a/Solutions/114.py +++ b/Solutions/114.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string and a set of delimiters, reverse the words in the string while maintaining the relative order of the delimiters. @@ -8,12 +8,12 @@ Input = "hello/world:here" Output = "here/world:hello" -''' +""" # FUNCTION TO PERFORM THE OPERATION def rev_words(string, delimiters): # if the string is empty, its returned - if (len(string) == 0): + if len(string) == 0: return string # words stores the words in the string @@ -21,7 +21,7 @@ def rev_words(string, delimiters): # delims stores the delimiters in the string delims = [] # flag_beg checks whether the 1st character is a delimiter - flag_beg = (string[0] in delimiters) + flag_beg = string[0] in delimiters # flag_delim checks whether the current string is a delimiter flag_delim = False # temp stores the current part of the string (word or delimiter) @@ -30,14 +30,14 @@ def rev_words(string, delimiters): # iterating over the string for char in string: # if the character is a delimiter - if (char in delimiters): + if char in delimiters: # if temp contains delimiters - if (flag_delim): + if flag_delim: # the character is added to temp temp += char else: # if temp contained a word, its added to word list - if (temp): + if temp: words.append(temp) # temp is set to the current delimiter and flag_delim is set temp = char @@ -45,7 +45,7 @@ def rev_words(string, delimiters): # if the character is not a delimiter else: # if temp contains delimiters, flag is reset, temp is added to delimiters and set to the current character - if (flag_delim): + if flag_delim: flag_delim = False delims.append(temp) temp = char @@ -54,7 +54,7 @@ def rev_words(string, delimiters): temp += char # if the last character is a delimiter, its added to delimiter - if (flag_delim): + if flag_delim: delims.append(temp) # else its added to words else: @@ -75,12 +75,12 @@ def rev_words(string, delimiters): res = "" # if flag_beg is set, we add the 1st delimiter and increment j - if (flag_beg): + if flag_beg: j = 1 res += delims[0] # looping till the end of the end of the lists - while (i < len_words or j < len_delims): + while i < len_words or j < len_delims: # checking for exceptions try: # adding the words and delimiters and incrementing i and j @@ -94,10 +94,11 @@ def rev_words(string, delimiters): return res + # DRIVER CODE print(rev_words("hello/world:here", [":", "/"])) print(rev_words("here/world:hello", [":", "/"])) print(rev_words("hello/world:here/", [":", "/"])) print(rev_words("hello//world:here", [":", "/"])) print(rev_words("hello", [":", "/"])) -print(rev_words("//:", [":", "/"])) \ No newline at end of file +print(rev_words("//:", [":", "/"])) diff --git a/Solutions/115.py b/Solutions/115.py index 0f4e726..ff70397 100644 --- a/Solutions/115.py +++ b/Solutions/115.py @@ -1,10 +1,10 @@ -''' +""" Problem: Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node's descendants. The tree s could also be considered as a subtree of itself. -''' +""" # local import from DataStructures module from DataStructures.Tree import Binary_Tree, Node @@ -12,49 +12,53 @@ # equality function for Node class (checks the entire subtree) def __eq__(self, other): # checking if any of the node is empty or other's type is a mismatch - if ((not self) or (not other) or (type(other) != Node)): + if (not self) or (not other) or (type(other) != Node): return False - + # if the values they hold are different, False is returned - if (self.val != other.val): + if self.val != other.val: return False - + # returning the value for the similarity of the children (recursive) - return (self.left == other.left and self.right == other.right) + return self.left == other.left and self.right == other.right + # helper function to all occourances where the value is same def find_helper(self, tree_search): # checking the equality of the subtree - if (self == tree_search): + if self == tree_search: return True - + # if the subtree was not same, the children are checked - if (self.left and self.left.find_helper(tree_search)): + if self.left and self.left.find_helper(tree_search): return True - if (self.right and self.right.find_helper(tree_search)): + if self.right and self.right.find_helper(tree_search): return True - + # if no match was found, False is returned - return False + return False + # function to perform the pre-requisite checks and calling the find_helper def match(self, other): # checking if the other object has the same class and has a root Node and the tree has a root node too, the result of the check is returned - if (type(other) == Binary_Tree and other.root and self.root): + if type(other) == Binary_Tree and other.root and self.root: return self.root.find_helper(other.root) # else False is returned else: return False + # adding the custom created functions to the classes -setattr(Node, '__eq__', __eq__) -setattr(Node, 'find_helper', find_helper) -setattr(Binary_Tree, 'match', match) +setattr(Node, "__eq__", __eq__) +setattr(Node, "find_helper", find_helper) +setattr(Binary_Tree, "match", match) # FUNCTION TO PERFORM THE OPERATION def get_match(s, t): return s.match(t) + # DRIVER CODE tree1 = Binary_Tree() tree1.root = Node(0) @@ -74,4 +78,4 @@ def get_match(s, t): tree3.root.right = Node(5) print(get_match(tree1, tree2)) -print(get_match(tree1, tree3)) \ No newline at end of file +print(get_match(tree1, tree3)) diff --git a/Solutions/116.py b/Solutions/116.py index 398419d..907576e 100644 --- a/Solutions/116.py +++ b/Solutions/116.py @@ -1,15 +1,16 @@ -''' +""" Problem: Generate a finite, but an arbitrarily large binary tree quickly in O(1). That is, generate() should return a tree whose size is unbounded but finite. -''' +""" # local import from the DataStructures module from DataStructures.Tree import Node, Binary_Tree # library imports from random import random, randint + # matplotlib is used to plot the distribution (not mandatory) import matplotlib.pyplot as plt @@ -19,49 +20,52 @@ def generate_helper(self, probability=0.5, probability_branch=0.5): prob_res = random() # if the number is larger than the probabilty, the branch generation is stopped - if (prob_res > probability): + if prob_res > probability: return - + # generating random numbers for left and right branch prob_res_left = random() prob_res_right = random() # generating the left branch based on probability - if (prob_res_left < probability_branch): + if prob_res_left < probability_branch: self.left = Node(randint(1, 1000)) self.left.generate_helper(probability, probability_branch) # generating the right branch based on probability - if (prob_res_right < probability_branch): + if prob_res_right < probability_branch: self.right = Node(randint(1, 1000)) self.right.generate_helper(probability, probability_branch) + # len function helper (member of Node class) def tree_length_helper(self): # getting the the left height - if (self.left): + if self.left: left = self.left.tree_length_helper() else: left = 0 - + # getting the the right height - if (self.right): + if self.right: right = self.right.tree_length_helper() else: right = 0 - + # returning the sum of left, right and 1 (as the subtree consists of left and right children and the node itself) - return (left + right + 1) + return left + right + 1 + # len function for the binary tree class def __len__(self): - if (self.root): + if self.root: return self.root.tree_length_helper() return 0 + # adding the necessary functions to the classses -setattr(Node, 'generate_helper', generate_helper) -setattr(Node, 'tree_length_helper', tree_length_helper) -setattr(Binary_Tree, '__len__', __len__) +setattr(Node, "generate_helper", generate_helper) +setattr(Node, "tree_length_helper", tree_length_helper) +setattr(Binary_Tree, "__len__", __len__) # FUNCTION TO PERFORM THE OPERATION def generate(): @@ -75,7 +79,8 @@ def generate(): # returning the tree return tree -#DRIVER CODE + +# DRIVER CODE res = [] for i in range(1000): @@ -84,4 +89,4 @@ def generate(): plt.xlim(right=2500, left=100) plt.ylim(top=100) plt.hist(res, bins=50) -plt.show() \ No newline at end of file +plt.show() diff --git a/Solutions/117.py b/Solutions/117.py index f68a03d..c2dead1 100644 --- a/Solutions/117.py +++ b/Solutions/117.py @@ -1,8 +1,8 @@ -''' +""" Problem: Given a binary tree, return the level of the tree with minimum sum. -''' +""" # local import from the DataStructures module from DataStructures.Queue import Queue @@ -11,7 +11,7 @@ # FUNCTION TO PERFROM THE OPERATION def get_min_sum(tree): # if the tree is empty, 0 is returned - if (not tree.root): + if not tree.root: return 0 # creating a queue @@ -25,38 +25,39 @@ def get_min_sum(tree): min_sum = 99999 # temp_sum stores the sum of the current level temp_sum = 0 - + # processing all the nodes (till the queue is empty) - while (not queue_processing.isEmpty()): + while not queue_processing.isEmpty(): # getting the current node node = queue_processing.dequeue() # if the node is not None - if (node): + if node: # the children of the node are added to the queue - if (node.left): + if node.left: queue_processing.enqueue(node.left) - if (node.right): + if node.right: queue_processing.enqueue(node.right) - + # the node's value is added to temp_sum temp_sum += node.val - + # if the node is None (end of a level) else: # if the level's sum is less than the min_sum, min_sum is updated - if (temp_sum < min_sum): + if temp_sum < min_sum: min_sum = temp_sum # if the queue has any elements, another None is added to demarkate the end of the current level # length checking is necessary as if all the nodes are processed, it will keep adding Nones and the loop will go on infinitely - if (len(queue_processing) > 0): + if len(queue_processing) > 0: queue_processing.enqueue(None) temp_sum = 0 - + # min_sum is returned return min_sum + # DRIVER CODE a = Node(100) b = Node(200) @@ -86,4 +87,4 @@ def get_min_sum(tree): b.val = 1500 print(get_min_sum(tree)) h.val = 2000 -print(get_min_sum(tree)) \ No newline at end of file +print(get_min_sum(tree)) diff --git a/Solutions/118.py b/Solutions/118.py index 1c8fdc6..d652685 100644 --- a/Solutions/118.py +++ b/Solutions/118.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a sorted list of integers, square the elements and give the output in sorted order. @@ -7,7 +7,7 @@ Input = [-9, -2, 0, 2, 3] Output = [0, 4, 4, 9, 81] -''' +""" # helper function to merge 2 sorted list into 1 sorted list def merge_sorted_lists(arr1, arr2): @@ -21,22 +21,23 @@ def merge_sorted_lists(arr1, arr2): result = [] # iterating till the end of one of the arrays - while (ptr1 < length1 and ptr2 < length2): + while ptr1 < length1 and ptr2 < length2: # finding the smaller element of the 2 arrays' current position and adding it to the result - if (arr1[ptr1] < arr2[ptr2]): + if arr1[ptr1] < arr2[ptr2]: result.append(arr1[ptr1]) ptr1 += 1 - + else: result.append(arr2[ptr2]) ptr2 += 1 - + # extending the result by the left over part of the unfinished array result.extend(arr1[ptr1:]) result.extend(arr2[ptr2:]) return result + # FUNCTION TO PERFORM THE OPERATION def sort_square(arr): # pos_start stores the starting index of the positive numbers @@ -47,13 +48,13 @@ def sort_square(arr): # looping over the array for i in range(length): # if the element is poitive, pos_start is updated and the control breaks out of the loop - if (arr[i] > 0): + if arr[i] > 0: pos_start = i break # if all elements are negative, pos_start is set to the length of the array else: pos_start = length - + # generating the poitive and negative parts negative_part = [elem * elem for elem in arr[:pos_start][::-1]] positive_part = [elem * elem for elem in arr[pos_start:]] @@ -61,10 +62,11 @@ def sort_square(arr): # returning the final sorted list return merge_sorted_lists(positive_part, negative_part) + # DRIVER CODE print(sort_square([])) print(sort_square([0])) print(sort_square([-1, 1])) print(sort_square([0, 2, 3])) print(sort_square([-9, -2, 0])) -print(sort_square([-9, -2, 0, 2, 3])) \ No newline at end of file +print(sort_square([-9, -2, 0, 2, 3])) diff --git a/Solutions/119.py b/Solutions/119.py index 63bc953..d0dd5b1 100644 --- a/Solutions/119.py +++ b/Solutions/119.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a set of closed intervals, find the smallest set of numbers that covers all the intervals. @@ -8,7 +8,7 @@ Input = [[0, 3], [2, 6], [3, 4], [6, 9]] Output = [3, 6] -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_spanning_interval(intervals): @@ -21,7 +21,7 @@ def get_spanning_interval(intervals): # getting the number of intervals included in the 1st interval for interval in intervals[1:]: - if (interval[0] < start and interval[1] < start): + if interval[0] < start and interval[1] < start: start = interval[1] pos += 1 else: @@ -29,12 +29,13 @@ def get_spanning_interval(intervals): # updating the value of end by iterating through the intervals and checking for interval in intervals[pos:]: - if (interval[0] > end): + if interval[0] > end: end = interval[0] - + # returning a tuple of start and end return start, end + # DRIVER CODE print(get_spanning_interval([[0, 3]])) print(get_spanning_interval(([[0, 3], [2, 6]]))) @@ -42,4 +43,4 @@ def get_spanning_interval(intervals): print(get_spanning_interval(([[0, 3], [2, 6], [3, 4], [6, 7]]))) print(get_spanning_interval(([[0, 3], [2, 6], [3, 4], [6, 9]]))) print(get_spanning_interval(([[0, 3], [2, 6], [3, 4], [6, 100]]))) -print(get_spanning_interval([[0,4], [1,2], [5,6]])) \ No newline at end of file +print(get_spanning_interval([[0, 4], [1, 2], [5, 6]])) diff --git a/Solutions/12.py b/Solutions/12.py index 0612ffc..26ecc56 100644 --- a/Solutions/12.py +++ b/Solutions/12.py @@ -1,4 +1,4 @@ -''' +""" Problem: There exists a staircase with N steps, and you can climb up either 1 or 2 steps at a @@ -16,14 +16,14 @@ What if, instead of being able to climb 1 or 2 steps at a time, you could climb any number from a set of positive integers X? For example, if X = {1, 3, 5}, you could climb 1, 3, or 5 steps at a time. -''' +""" from typing import List def count_ways(steps: int, permissable_steps: List[int] = [1, 2]) -> int: # dynamic array to store the number of ways a step can be reached - num_ways = [0 for i in range(steps+1)] + num_ways = [0 for i in range(steps + 1)] # base case num_ways[0] = 1 # calculating using the formula steps_i = sum(steps_i(i - j)) @@ -46,10 +46,10 @@ def count_ways(steps: int, permissable_steps: List[int] = [1, 2]) -> int: print(count_ways(6, [1, 3, 5])) -''' +""" SPECS: TIME COMPLEXITY: O(n) SPACE COMPLEXITY: O(n) [n = number of steps] -''' +""" diff --git a/Solutions/120.py b/Solutions/120.py index a89cc27..ad8e16e 100644 --- a/Solutions/120.py +++ b/Solutions/120.py @@ -1,9 +1,9 @@ -''' +""" Problem: Implement the singleton pattern with a twist. First, instead of storing one instance, store two instances. And in every even call of getInstance(), return the first instance and in every odd call of getInstance(), return the second instance. -''' +""" # class to handle the operations class Twisted_Singleton: @@ -22,11 +22,11 @@ def __init__(self, instance_num): @staticmethod def initialize(): # only if the flag is set, will the data be initialized (used to ensure it cannot be reinitialized) - if (Twisted_Singleton.flag): + if Twisted_Singleton.flag: Twisted_Singleton.instances.append(Twisted_Singleton(1)) Twisted_Singleton.instances.append(Twisted_Singleton(2)) Twisted_Singleton.flag = False - + # FUNCTION TO PERFORM THE OPERATION @staticmethod def getInstance(): @@ -34,11 +34,12 @@ def getInstance(): Twisted_Singleton.is_odd = not Twisted_Singleton.is_odd # returning the necessary data - if (Twisted_Singleton.is_odd): + if Twisted_Singleton.is_odd: return Twisted_Singleton.instances[0].instance_num return Twisted_Singleton.instances[1].instance_num + # DRIVER CODE Twisted_Singleton.initialize() @@ -47,4 +48,4 @@ def getInstance(): print(Twisted_Singleton.getInstance()) print(Twisted_Singleton.getInstance()) print(Twisted_Singleton.getInstance()) -print(Twisted_Singleton.getInstance()) \ No newline at end of file +print(Twisted_Singleton.getInstance()) diff --git a/Solutions/121.py b/Solutions/121.py index 49afa46..57e396e 100644 --- a/Solutions/121.py +++ b/Solutions/121.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string which we can delete at most k, return whether you can make a palindrome. @@ -7,33 +7,35 @@ Input = 'waterrfetawx', 2 Output = True ('f' and 'x can be deleted to yield 'waterretaw') -''' +""" # function to check if a string is palindrome def is_palindrome(string): - return (string == string[::-1]) + return string == string[::-1] + # FUNCTION TO PERFORM THE OPERATION def can_make_palindrome(string, k): # base case 1 for recursion: if the string is a palindrome, True is returned - if (is_palindrome(string)): + if is_palindrome(string): return True - + # base case 2 for recursion: if k = 0, False is returned - if (not k): + if not k: return False - + # iterating over the string for i in range(len(string)): - # testing all string if they are palindrome (eleminating the i'th character) + # testing all string if they are palindrome (eleminating the i'th character) # recursively called function, so all possible combinations of removing k characters will be found till one is palindrome # if a palindrome is encountered, True is returned - if (can_make_palindrome(string[:i] + string[i+1:], k-1)): + if can_make_palindrome(string[:i] + string[i + 1 :], k - 1): return True - + # if no palindrome can be formed, False is returned return False + # DRIVER CODE print(can_make_palindrome("a", 0)) print(can_make_palindrome("aaa", 2)) @@ -44,4 +46,4 @@ def can_make_palindrome(string, k): print(can_make_palindrome("malayalam", 0)) print(can_make_palindrome("malayalam", 1)) print(can_make_palindrome("asdf", 5)) -print(can_make_palindrome("asdf", 2)) \ No newline at end of file +print(can_make_palindrome("asdf", 2)) diff --git a/Solutions/122.py b/Solutions/122.py index 78c183d..985c23e 100644 --- a/Solutions/122.py +++ b/Solutions/122.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given a 2-d matrix where each cell represents number of coins in that cell. @@ -10,7 +10,7 @@ [2, 0, 0, 4], [1, 5, 3, 1]] Output = 12 (0 + 2 + 1 + 5 + 3 + 1 = 12 coins) -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_max_coins(mat): @@ -22,22 +22,15 @@ def get_max_coins(mat): for i in range(1, n): for j in range(1, m): # updating the values of the matrix - mat[i][j] = max(mat[i-1][j], mat[i][j-1]) + mat[i][j] - + mat[i][j] = max(mat[i - 1][j], mat[i][j - 1]) + mat[i][j] + # returning the result at the last column of the last row - return mat[n-1][m-1] + return mat[n - 1][m - 1] + # DRIVER CODE -mat = [ - [0, 3, 1, 1], - [2, 0, 0, 4], - [1, 5, 3, 1] -] +mat = [[0, 3, 1, 1], [2, 0, 0, 4], [1, 5, 3, 1]] print(get_max_coins(mat)) -mat = [ - [0, 3, 1, 1], - [2, 8, 9, 4], - [1, 5, 3, 1] -] -print(get_max_coins(mat)) \ No newline at end of file +mat = [[0, 3, 1, 1], [2, 8, 9, 4], [1, 5, 3, 1]] +print(get_max_coins(mat)) diff --git a/Solutions/123.py b/Solutions/123.py index aa69d40..cbb6b77 100644 --- a/Solutions/123.py +++ b/Solutions/123.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string, return whether it represents a number. @@ -15,7 +15,7 @@ * "x 1" * "a -2" * "-" -''' +""" # FUNCTION TO PERFORM THE OPERATION def check(string): @@ -35,10 +35,10 @@ def check(string): # if the current character is not a number if not (i.isdigit()): # checking the number of the corresponding symbol, if the number of the same symbol is greater than 1, it is not valid [exceptions are there] - if (i == "-"): - if (num_neg >= 1): + if i == "-": + if num_neg >= 1: # if the string contains an 'e' we can have 2 '-'s (for mantissa and exponent) [exception] - if (num_neg == 1 and num_e == 1): + if num_neg == 1 and num_e == 1: num_neg += 1 continue @@ -47,10 +47,10 @@ def check(string): else: num_neg += 1 - elif (i == "."): - if (num_pt >= 1): + elif i == ".": + if num_pt >= 1: # if the string contains an 'e' we can have 2 '.'s (for mantissa and exponent) [exception] - if (num_pt == 1 and num_e == 1): + if num_pt == 1 and num_e == 1: num_pt += 1 continue @@ -58,28 +58,29 @@ def check(string): break else: num_pt += 1 - - elif (i == "e"): - if (num_e >= 1): + + elif i == "e": + if num_e >= 1: isValid = False break else: num_e += 1 - + # if the character is a space, its ignored - elif (i == " "): + elif i == " ": pass - + # any other character makes the string invalid else: isValid = False break - + # if the current character is a number hasNum is set to True else: hasNum = True - - return (isValid and hasNum) + + return isValid and hasNum + # DRIVER CODE print(check("10")) @@ -92,4 +93,4 @@ def check(string): print(check("a")) print(check("x 1")) print(check("a -2")) -print(check("-")) \ No newline at end of file +print(check("-")) diff --git a/Solutions/124.py b/Solutions/124.py index 91f23b1..d68620f 100644 --- a/Solutions/124.py +++ b/Solutions/124.py @@ -1,11 +1,11 @@ -''' +""" Problem: You have 100 fair coins and you flip them all at the same time. Any that come up tails you set aside. The ones that come up heads you flip again. How many rounds do you expect to play before only one coin remains? Write a function that, given 'n', returns the number of rounds you'd expect to play until one coin remains. -''' +""" # imports from the math module from math import log2, ceil @@ -16,8 +16,9 @@ def expectation(n): # ceil is used to round it off to the next larger integer as number of tosses cannot be a fraction return ceil(log2(n)) + # DRIVER CODE print(expectation(1)) print(expectation(2)) print(expectation(100)) -print(expectation(200)) \ No newline at end of file +print(expectation(200)) diff --git a/Solutions/125.py b/Solutions/125.py index 75d60a5..7e81527 100644 --- a/Solutions/125.py +++ b/Solutions/125.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given the root of a binary search tree, and a target K, return two nodes in the tree whose sum equals K. @@ -12,7 +12,7 @@ / \ 11 15 Output = 5, 15 -''' +""" # local import from the Datastructure module from DataStructures.Tree import Binary_Tree, Node @@ -20,57 +20,60 @@ # traversal helper function for the node class (generator function for inorder traversal) def traverse_helper(self): # if left child exists - if (self.left): + if self.left: # the function is called recursively to generate all children for val in self.left.traverse_helper(): # the node's value is yielded (to keep the function in memory) yield val - + # the current node's value is yielded (to keep the function in memory) yield self.val # if right child exists - if (self.right): + if self.right: # the function is called recursively to generate all children for val in self.right.traverse_helper(): # the node's value is yielded (to keep the function in memory) yield val + # traverse function for the tree class def traverse(self): # the tree has nodes, the traversal enerator is returned - if (self.root): + if self.root: return self.root.traverse_helper() # None is returned if the tree is empty return None + # adding the necessary functions to the respective classes -setattr(Node, 'traverse_helper', traverse_helper) -setattr(Binary_Tree, 'traverse', traverse) +setattr(Node, "traverse_helper", traverse_helper) +setattr(Binary_Tree, "traverse", traverse) # FUNCTION TO PERFORM THE OPERATION def get_target_sum(tree, k): - # getting the generator + # getting the generator generator = tree.traverse() # if the generator is None, the tree is empty, None is returned - if (not generator): + if not generator: return None - + # previous is a set of previously seen values previous = set() # getting the values from the generator for val in generator: # if (k - val) is in the set, (k - val) and the current value is returned - if ((k - val) in previous): + if (k - val) in previous: return (k - val), val # if (k - val) is not found, the current valu is added to the set previous.add(val) - + # if the target sum cannot be reached by 2 values in the tree, a tuple of 2 None is returned return None, None + # DRIVER CODE tree = Binary_Tree() tree.root = Node(10) @@ -84,4 +87,4 @@ def get_target_sum(tree, k): print(get_target_sum(tree, 21)) print(get_target_sum(tree, 25)) print(get_target_sum(tree, 30)) -print(get_target_sum(tree, 35)) \ No newline at end of file +print(get_target_sum(tree, 35)) diff --git a/Solutions/126.py b/Solutions/126.py index da6ea49..5f9fc45 100644 --- a/Solutions/126.py +++ b/Solutions/126.py @@ -1,4 +1,4 @@ -''' +""" Problem: Write a function that rotates a list by k elements. @@ -8,7 +8,7 @@ Input = [1, 2, 3, 4, 5, 6] Output = [3, 4, 5, 6, 1, 2] -''' +""" # FUNCTION TO PERFORM THE OPERATION def rotate_list(List, k): @@ -21,14 +21,15 @@ def rotate_list(List, k): for _ in range(k): temp = List.pop(0) List.append(temp) - + # returning the list return List + # DRIVER CODE print(rotate_list([1, 2, 3, 4, 5, 6], 0)) print(rotate_list([1, 2, 3, 4, 5, 6], 2)) print(rotate_list([1, 2, 3, 4, 5, 6], 4)) print(rotate_list([1, 2, 3, 4, 5, 6], 6)) print(rotate_list([1, 2, 3, 4, 5, 6], 10)) -print(rotate_list([1, 2, 3, 4, 5, 6], 1000000000)) \ No newline at end of file +print(rotate_list([1, 2, 3, 4, 5, 6], 1000000000)) diff --git a/Solutions/127.py b/Solutions/127.py index 937d691..bf28568 100644 --- a/Solutions/127.py +++ b/Solutions/127.py @@ -1,4 +1,4 @@ -''' +""" Problem: Let's represent an integer in a linked list format by having each node represent a digit in the number. @@ -13,7 +13,7 @@ Input = 9 -> 9, 5 -> 2 Output = 4 -> 2 -> 1 [124 = 99 + 25] -''' +""" # local import from the Datastructure module from DataStructures.LinkedList import Node, Linked_list @@ -21,15 +21,16 @@ # function to add node at the rear of a linked list def add(self, val=0): # if there are no nodes, a node is created and both head and rear points to it - if (self.head == None): + if self.head == None: self.head = Node(val) self.rear = self.head - + # if a node already exists, the new node is added to the rear else: self.rear.next = Node(val) self.rear = self.rear.next + # function to add 2 linked lists def __add__(self, other): # ans stores the funal result @@ -44,71 +45,73 @@ def __add__(self, other): temp = 0 # iterating till the end of both the lists - while (pos1 or pos2): + while pos1 or pos2: # if the 1st list is empty - if (pos1 == None): + if pos1 == None: # the sum is obtained temp = pos2.val + carry - + # the carry is obtained - if (temp >= 10): + if temp >= 10: carry = 1 temp -= 10 else: carry = 0 - + # if the 2nd list is empty - elif (pos2 == None): + elif pos2 == None: # the sum is obtained temp = pos1.val + carry - + # the carry is obtained - if (temp >= 10): + if temp >= 10: carry = 1 temp -= 10 else: carry = 0 - + # if both the lists have value in the current position else: # the sum is obtained temp = pos2.val + pos1.val + carry # the carry is obtained - if (temp >= 10): + if temp >= 10: carry = 1 temp -= 10 else: carry = 0 - + # adding the necessary value ans.add(temp) # moving to the next value - if (pos1): + if pos1: pos1 = pos1.next - if (pos2): + if pos2: pos2 = pos2.next - + # if at the end, there is a carry, its added to the linked list - if (carry == 1): + if carry == 1: ans.add(1) - + return ans + # adding the necessary functions to the linked list class -setattr(Linked_list, 'add', add) -setattr(Linked_list, '__add__', __add__) +setattr(Linked_list, "add", add) +setattr(Linked_list, "__add__", __add__) # function to generate a linked list from a number def create(val): LL = Linked_list() - while (val > 0): + while val > 0: LL.add(val % 10) val = val // 10 - + return LL + # DRIVER CODE LL1 = create(99) LL2 = create(25) @@ -123,4 +126,4 @@ def create(val): print(LL1) print(LL2) -print(LL1 + LL2) \ No newline at end of file +print(LL1 + LL2) diff --git a/Solutions/128.py b/Solutions/128.py index faff0cd..6357650 100644 --- a/Solutions/128.py +++ b/Solutions/128.py @@ -1,4 +1,4 @@ -''' +""" Problem: The Tower of Hanoi is a puzzle game with three rods and n disks, each a different size. @@ -22,36 +22,39 @@ Move 2 to 1 Move 2 to 3 Move 1 to 3 -''' +""" # FUNCTION TO PERFORM THE OPERATION def towers_of_hanoi(n, start_rod=None, aux_rod=None, end_rod=None): # on the first call of the function, the rod names are initialized and a small intro printed - if (not start_rod): + if not start_rod: # initialized name for the rod, not using the convention mentioned in the question - start_rod = 'start_rod' - print(f"\nTower of Hanoi for {n} Disks ========================================") - if (not aux_rod): + start_rod = "start_rod" + print( + f"\nTower of Hanoi for {n} Disks ========================================" + ) + if not aux_rod: # initialized name for the rod, not using the convention mentioned in the question - aux_rod = 'aux_rod' - if (not end_rod): + aux_rod = "aux_rod" + if not end_rod: # initialized name for the rod, not using the convention mentioned in the question - end_rod = 'end_rod' + end_rod = "end_rod" # if the number of disks left to move is 1, its just shifted [base case for recursion] - if (n == 1): - print(f'Move disk 1 from {start_rod} to {end_rod}') + if n == 1: + print(f"Move disk 1 from {start_rod} to {end_rod}") return - + # moving the top disk of the start rod to the proper position in the auxilary rod using the end rod as buffer - towers_of_hanoi(n-1, start_rod, end_rod, aux_rod) + towers_of_hanoi(n - 1, start_rod, end_rod, aux_rod) # moving the top disk from the start rod to the end rod - print(f'Move disk {n} from {start_rod} to {end_rod}') + print(f"Move disk {n} from {start_rod} to {end_rod}") # moving the top disk of the auxilary rod to the proper position in the end rod using the start rod as buffer - towers_of_hanoi(n-1, aux_rod, start_rod, end_rod) + towers_of_hanoi(n - 1, aux_rod, start_rod, end_rod) + # DRIVER CODE towers_of_hanoi(3) towers_of_hanoi(4) towers_of_hanoi(5) -towers_of_hanoi(6) \ No newline at end of file +towers_of_hanoi(6) diff --git a/Solutions/129.py b/Solutions/129.py index 5e13490..4d4f717 100644 --- a/Solutions/129.py +++ b/Solutions/129.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a real number n, find the square root of n. @@ -7,14 +7,15 @@ Input = 9 Output = 3 -''' +""" # global value for tolerence TOLERENCE = 10 ** (-6) # helper function to check whether 2 numbers are almost equal (within the tolerence limit) def almost_equal(num1, num2): - return (num1 + TOLERENCE > num2 and num1 - TOLERENCE < num2) + return num1 + TOLERENCE > num2 and num1 - TOLERENCE < num2 + # FUNCTION TO PERFORM THE OPERATION def get_sqrt(num): @@ -31,20 +32,21 @@ def get_sqrt(num): # temp stores the square of mid temp = mid * mid - # if temp is equal to the passed number, mid is the square root + # if temp is equal to the passed number, mid is the square root # its rounded to 6 decimal places and returned - if (almost_equal(temp, num)): + if almost_equal(temp, num): return round(mid, 6) - + # depending upon the value of temp, the next search domain is restricted (check binary search for details) - elif (temp < num): + elif temp < num: low = mid + 1 - + else: high = mid - 1 + # DRIVER CODE print(get_sqrt(100)) print(get_sqrt(9)) print(get_sqrt(3)) -print(get_sqrt(2)) \ No newline at end of file +print(get_sqrt(2)) diff --git a/Solutions/13.py b/Solutions/13.py index 62f86e1..1d0d674 100644 --- a/Solutions/13.py +++ b/Solutions/13.py @@ -1,9 +1,9 @@ -''' +""" Problem: Given an integer k and a string s, find the length of the longest substring that contains at most k distinct characters. For example, "abcba", 2 => 'bcb' -''' +""" # FUNCTION TO PERFORM THE OPERATION def longest_substring_k_unique(string, k, length): @@ -17,11 +17,11 @@ def longest_substring_k_unique(string, k, length): num_unique = 1 # Loop to go over the entire string - while (end < (length)): + while end < (length): # if the last character is already in the longest_substring_till_now, the value in the map is incremented - if (string[end] in hash_map and hash_map[string[end]] != 0): + if string[end] in hash_map and hash_map[string[end]] != 0: hash_map[string[end]] += 1 - + else: # if the last value is not in longest_substring_till_now, the value in the map is incremented # num_unique is incremented @@ -29,30 +29,31 @@ def longest_substring_k_unique(string, k, length): num_unique += 1 # if the number of unique characters excede k, then 1 by 1 charcters are removed from the start, till there are k unique values - if (num_unique > k): - while (num_unique > k): + if num_unique > k: + while num_unique > k: hash_map[string[start]] -= 1 - if (hash_map[string[start]] == 0): + if hash_map[string[start]] == 0: num_unique -= 1 start += 1 # forming the new string - temp = string[start: end+1] + temp = string[start : end + 1] # if the new string is longer than longest_substring_till_now, longest_substring_till_now is overwritten - if (num_unique == k and len(temp) > len(longest_substring_till_now)): + if num_unique == k and len(temp) > len(longest_substring_till_now): longest_substring_till_now = temp - + end += 1 - + # if the number of unique charcters is equal to k, the longest_substring_till_now is returned # else and empty string is returned (if there are less than k unique characters in s) - if (num_unique == k): + if num_unique == k: return longest_substring_till_now else: - return '' + return "" + # DRIVER CODE print(longest_substring_k_unique("abcba", 2, len("abcba"))) print(longest_substring_k_unique("abcba", 20, len("abcba"))) -print(longest_substring_k_unique("karappa", 2, len("karappa"))) \ No newline at end of file +print(longest_substring_k_unique("karappa", 2, len("karappa"))) diff --git a/Solutions/130.py b/Solutions/130.py index 4262460..5100fe6 100644 --- a/Solutions/130.py +++ b/Solutions/130.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an array of numbers representing the stock prices of a company in chronological order and an integer k. @@ -9,40 +9,54 @@ Input = [5, 2, 4, 0, 1], 2 Output = 3 -''' +""" # helper function for the computation def max_profit_helper(arr, curr_index, curr_profit, buys_left, sells_left): - # if the end of the array is reached or no more sells can be performed + # if the end of the array is reached or no more sells can be performed # current profit is returned (base case for recursion) - if (curr_index == len(arr) or sells_left == 0): + if curr_index == len(arr) or sells_left == 0: return curr_profit - + # if the number of buys left and sells left are equal, we have to buy a stock - if (buys_left == sells_left): + if buys_left == sells_left: # returning the max profit we can obtain return max( # wait for a different deal - max_profit_helper(arr, curr_index+1, curr_profit, buys_left, sells_left), + max_profit_helper(arr, curr_index + 1, curr_profit, buys_left, sells_left), # buy at the current price - max_profit_helper(arr, curr_index+1, curr_profit-arr[curr_index], buys_left-1, sells_left) - ) + max_profit_helper( + arr, + curr_index + 1, + curr_profit - arr[curr_index], + buys_left - 1, + sells_left, + ), + ) # if the number of buys left and sells left are inequal, we have to sell a stock else: # returning the max profit we can obtain return max( # wait and hold for selling at a different price - max_profit_helper(arr, curr_index+1, curr_profit, buys_left, sells_left), + max_profit_helper(arr, curr_index + 1, curr_profit, buys_left, sells_left), # sell at the current price - max_profit_helper(arr, curr_index+1, curr_profit+arr[curr_index], buys_left, sells_left-1) + max_profit_helper( + arr, + curr_index + 1, + curr_profit + arr[curr_index], + buys_left, + sells_left - 1, + ), ) + # FUNCTION TO PERFORM THE OPERATION def max_profit(arr, k): # offloading the computation to the helper function return max_profit_helper(arr, 0, 0, k, k) + # DRIVER CODE print(max_profit([5, 2, 4, 0, 1], 2)) print(max_profit([5, 2, 4], 2)) -print(max_profit([5, 2, 4], 1)) \ No newline at end of file +print(max_profit([5, 2, 4], 1)) diff --git a/Solutions/131.py b/Solutions/131.py index affacfe..bd7c2e2 100644 --- a/Solutions/131.py +++ b/Solutions/131.py @@ -1,9 +1,9 @@ -''' +""" Problem: You are given the head to a singly linked list, where each node also has a 'random' pointer that points to anywhere in the linked list. Deep clone the list. -''' +""" # local import from the Datastructure module from DataStructures.LinkedList import Linked_list, Node @@ -19,17 +19,18 @@ def rand_join(self, pos1, pos2): # moving the pointers to the required positions for _ in range(pos1): pos_source = pos_source.next - + for _ in range(pos2): pos_dest = pos_dest.next - + # setting the random pointer pos_source.random_ptr = pos_dest - + except: # raising Index Error if the poition is out of range raise IndexError("Given position is out of the Linked List") + # FUNCTION TO PERFORM THE OPERATION def clone(self): # clone head tracks the head of the cloned list @@ -45,36 +46,36 @@ def clone(self): pos1 = pos1.next pos1.next = pos2 pos1 = pos1.next - if (pos2 != None): + if pos2 != None: pos2 = pos2.next else: break - + # setting the clone head to the proper position clone_head = clone_head.next # pos1 stores the current element of the linked list pos1 = self.head - + # setting the random pointer of the cloned linked list (every 2nd element in the new linked list: a->[a]->b->[b]->c->[c]) - for _ in range(self.length-1): + for _ in range(self.length - 1): pos1.next.random_ptr = pos1.random_ptr pos1 = pos1.next.next - + # pos1 stores the current position (original linked list) pos1 = self.head # pos2 stores the current position (cloned linked list) pos2 = self.head.next # reverting the linked list to its original form - for _ in range(self.length-1): + for _ in range(self.length - 1): pos1.next = pos2.next pos2.next = pos2.next.next pos1 = pos1.next - if (pos2.next == None): + if pos2.next == None: break else: pos2 = pos2.next - + # creating the cloned linked list from the cloned head, pos2 (points to the rear) and length of original linked list cloned_LL = Linked_list() cloned_LL.head = clone_head @@ -83,10 +84,11 @@ def clone(self): return cloned_LL + # adding the necessary functions and variables to the classes -setattr(Node, 'random_ptr', None) -setattr(Linked_list, 'rand_join', rand_join) -setattr(Linked_list, 'clone', clone) +setattr(Node, "random_ptr", None) +setattr(Linked_list, "rand_join", rand_join) +setattr(Linked_list, "clone", clone) # DRIVER CODE LL = Linked_list() @@ -112,4 +114,4 @@ def clone(self): print("\nOriginal List:", LL) -print("Cloned List:", LL_clone) \ No newline at end of file +print("Cloned List:", LL_clone) diff --git a/Solutions/132.py b/Solutions/132.py index 678cb5a..792a64b 100644 --- a/Solutions/132.py +++ b/Solutions/132.py @@ -1,4 +1,4 @@ -''' +""" Problem: Design and implement a HitCounter class that keeps track of requests (or hits). @@ -9,7 +9,7 @@ * range(lower, upper): returns the number of hits that occurred between timestamps lower and upper (inclusive) Follow-up: What if our system has limited memory? -''' +""" # importing datetime from the datetime module from datetime import datetime @@ -23,22 +23,22 @@ def add_sorted(self, val): self.length += 1 # if there is no values in the list, its added to the head - if (not self.head): + if not self.head: self.head = Node(val) self.rear = self.head - + # if the value to be added is larger than all values in the list, its added after rear - elif (val > self.rear.val): + elif val > self.rear.val: self.rear.next = Node(val) self.rear = self.rear.next - + else: pos = self.head # else finding the proper position - while (pos.val < val): + while pos.val < val: pos = pos.next - + # overwriting the node's value with the new value and adding a new node with the node's old value next to the node temp = pos.val pos.val = val @@ -49,77 +49,80 @@ def add_sorted(self, val): pos.next = new_node # if the node is rear, its reset to the new node (end of the list) - if (pos == self.rear): + if pos == self.rear: self.rear = new_node + # helper function to get the number of nodes in the range def in_range(self, start, stop): # if there is no values in the list, 0 is returned - if (not self.head): + if not self.head: return 0 - + # moving to the proper position pos = self.head num = 0 - while (pos and pos.val < start): + while pos and pos.val < start: pos = pos.next - + # if we reach the end of the list, 0 is returned - if (not pos): + if not pos: return 0 - + # counting the number of elements in the range - while (pos and pos.val <= stop): + while pos and pos.val <= stop: pos = pos.next num += 1 - + return num + # adding the necessary functions to the Linked List class -setattr(Linked_list, 'add_sorted', add_sorted) -setattr(Linked_list, 'in_range', in_range) +setattr(Linked_list, "add_sorted", add_sorted) +setattr(Linked_list, "in_range", in_range) # HitCounter class class HitCounter: # initialization def __init__(self): self.List = Linked_list() - self.start = None + self.start = None self.end = None - + # record function to store timestamp def record(self, timestamp): # adding the data in sorted order self.List.add_sorted(timestamp) # keeping track of the smallest and largest timestamp - if (not self.start): + if not self.start: self.start = timestamp self.end = timestamp - - elif (timestamp < self.start): + + elif timestamp < self.start: self.start = timestamp - - elif (timestamp > self.end): + + elif timestamp > self.end: self.end = timestamp - + # total function to get the total number of hits def total(self): return len(self.List) - + # range function to get the number of hits in the time range def range(self, lower, upper): # checking if the values are in the range of the linked list - if (upper < self.start or lower > self.end): + if upper < self.start or lower > self.end: return 0 - + return self.List.in_range(lower, upper) - + # string function to display the object def __str__(self): return str(self.List) + # DRIVER CODE hc = HitCounter() @@ -156,4 +159,4 @@ def __str__(self): print("Number in range:") print(hc.range(datetime(2000, 1, 1, 1, 1, 5), datetime(2000, 1, 1, 1, 1, 15))) print(hc.range(datetime(2000, 1, 1, 1, 1, 0), datetime(2000, 1, 1, 1, 1, 25))) -print() \ No newline at end of file +print() diff --git a/Solutions/133.py b/Solutions/133.py index 4c2d1e4..75a7a35 100644 --- a/Solutions/133.py +++ b/Solutions/133.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a node in a binary search tree, return the next bigger element, also known as the inorder successor. @@ -13,7 +13,7 @@ / \ 22 35 Output = 30 -''' +""" # local import from Datastructure class from DataStructures.Tree import Node, Binary_Tree @@ -21,63 +21,66 @@ # function to find the required node def search(self, val): # if the node is found, its returned (base case for recursion) - if (self.val == val): + if self.val == val: return self - + # using the binary search tree property to execute binary search - if (val < self.val): - if (self.left): + if val < self.val: + if self.left: return self.left.search(val) # if the required node is not present, None is returned (base case for recursion) else: return None - + else: - if (self.right): + if self.right: return self.right.search(val) # if the required node is not present, None is returned (base case for recursion) else: return None + # helper function to compute the inorder successor def inorder_successor_helper(self): # if the node has a right child, by bst property, the left-most node in the right subtree is the inorder sucessor - if (self.right): + if self.right: pos = self.right - while (pos.left): + while pos.left: pos = pos.left - + return pos.val - + # if the node doesn't have a right child, the node's parent is the inorder sucessor else: - if (self.parent): + if self.parent: return self.parent.val else: return None + # FUNCTION TO PERFORM THE OPERATION def inorder_successor(self, val): # checking whether the tree has nodes - if (self.root): + if self.root: # getting the required node node = self.root.search(val) - + # getting the inorder successor - if (node): + if node: return node.inorder_successor_helper() else: raise Exception("Node not Found") - + else: raise Exception("Empty Tree") + # adding the necessary functions and data to the classes -setattr(Node, 'parent', None) -setattr(Node, 'search', search) -setattr(Node, 'inorder_successor_helper', inorder_successor_helper) -setattr(Binary_Tree, 'inorder_successor', inorder_successor) +setattr(Node, "parent", None) +setattr(Node, "search", search) +setattr(Node, "inorder_successor_helper", inorder_successor_helper) +setattr(Binary_Tree, "inorder_successor", inorder_successor) # DRIVER CODE root = Node(10) @@ -95,4 +98,4 @@ def inorder_successor(self, val): print(tree) print(tree.inorder_successor(22)) -print(tree.inorder_successor(10)) \ No newline at end of file +print(tree.inorder_successor(10)) diff --git a/Solutions/134.py b/Solutions/134.py index cb603f3..16021f3 100644 --- a/Solutions/134.py +++ b/Solutions/134.py @@ -1,4 +1,4 @@ -''' +""" Problem: You have a large array with most of the elements as zero. @@ -7,7 +7,7 @@ * init(arr, size): initialize with the original large array and size. * set(i, val): updates index at i with val. * get(i): gets the value at index i. -''' +""" # the Sparse Array class class SparseArray: @@ -21,29 +21,29 @@ def __init__(self, arr, size): # generating the array for index, val in enumerate(arr): # storing only the non-zero values - if (val != 0): + if val != 0: self.arr[index] = val - + # set function def set(self, pos, val): # if the index is out of range, IndexError is raised - if (pos > self.size): + if pos > self.size: raise IndexError # if the value is 0, its not set (if any value is present, its deleted) - if (val == 0): - if (pos in self.arr): + if val == 0: + if pos in self.arr: del self.arr[pos] # the value is set if its non-zero else: self.arr[pos] = val - + # get function def get(self, pos): # if the position is in the array range - if (pos < self.size): + if pos < self.size: # if the value is non-zero, its extracted from the dictionary and returned - if (pos in self.arr): + if pos in self.arr: return self.arr[pos] # else 0 is returned else: @@ -51,18 +51,19 @@ def get(self, pos): # if the position is out of range, IndexError is raised else: raise IndexError - + # string function to display the array def __str__(self): string = "" for pos in range(self.size): - if (pos in self.arr): + if pos in self.arr: string += f"{self.arr[pos]}, " else: string += "0, " - return ("[" + string.rstrip(" ,") + "]") + return "[" + string.rstrip(" ,") + "]" + # DRIVER CODE arr = SparseArray([1, 0, 0, 0, 3, 0, 2, 0], 8) @@ -76,4 +77,4 @@ def __str__(self): arr.set(0, 0) print(arr.get(0)) -print(arr) \ No newline at end of file +print(arr) diff --git a/Solutions/135.py b/Solutions/135.py index d574477..33ad3b7 100644 --- a/Solutions/135.py +++ b/Solutions/135.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a binary tree, find a minimum path sum from root to a leaf. @@ -13,7 +13,7 @@ / -1 Output = [10, 5, 1, -1] (sum 15) -''' +""" # local import from the Datastructure module from DataStructures.Tree import Binary_Tree, Node @@ -21,36 +21,37 @@ # helper function to perform the operations def minimum_path_sum_helper(self): # getting the minimum sum for the left subtree - if (self.left): + if self.left: left_sum, left = self.left.minimum_path_sum_helper() else: left_sum, left = None, None # getting the minimum sum for the right subtree - if (self.right): + if self.right: right_sum, right = self.right.minimum_path_sum_helper() else: right_sum, right = None, None - + # if its a leaf node (base case for recursion), the value and a list containing the value is returned - if (not left and not right): + if not left and not right: return self.val, [self.val] # if only left child is present, the updated values (updated using left sum and list) are returned - elif (left and not right): - return (left_sum+self.val), left+[self.val] + elif left and not right: + return (left_sum + self.val), left + [self.val] # if only right child is present, the updated values (updated using right sum and list) are returned - elif (right and not left): - return (right_sum+self.val), right+[self.val] + elif right and not left: + return (right_sum + self.val), right + [self.val] # if both children are present, the path with smaller sum is selected and values updated correspondingly else: - if (left_sum < right_sum): - return (left_sum+self.val), left+[self.val] + if left_sum < right_sum: + return (left_sum + self.val), left + [self.val] else: - return (right_sum+self.val), right+[self.val] + return (right_sum + self.val), right + [self.val] + -# FUNCTION TO PERFORM THE OPERATION +# FUNCTION TO PERFORM THE OPERATION def minimum_path_sum(self): # checking if the tree has nodes - if (self.root): + if self.root: # getting the path from the leaf to root and returning the reverse _, path = self.root.minimum_path_sum_helper() return path[::-1] @@ -58,9 +59,10 @@ def minimum_path_sum(self): else: raise ValueError("Empty Tree") + # adding the necessary functions to the classes -setattr(Node, 'minimum_path_sum_helper', minimum_path_sum_helper) -setattr(Binary_Tree, 'minimum_path_sum', minimum_path_sum) +setattr(Node, "minimum_path_sum_helper", minimum_path_sum_helper) +setattr(Binary_Tree, "minimum_path_sum", minimum_path_sum) # DRIVER CODE tree = Binary_Tree() @@ -69,4 +71,4 @@ def minimum_path_sum(self): tree.root.right = Node(5, right=Node(1, left=Node(-1))) print(tree) -print(tree.minimum_path_sum()) \ No newline at end of file +print(tree.minimum_path_sum()) diff --git a/Solutions/136.py b/Solutions/136.py index 88e83d4..59f29ec 100644 --- a/Solutions/136.py +++ b/Solutions/136.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an N by M matrix consisting only of 1's and 0's, find the largest rectangle containing only 1's and return its area. @@ -10,12 +10,13 @@ [1, 0, 1, 1], [0, 1, 0, 0]] Output = 4 -''' +""" # function to check if all elements in the given range is 1 (used to check if the covered rows can be extended) def extendable_row(matrix, erow, scol, ecol): return all(matrix[erow][scol:ecol]) + # function to check if all elements in the given range is 1 (used to check if the covered columns can be extended) def extendable_col(matrix, ecol, srow, erow): for row in range(srow, erow): @@ -23,6 +24,7 @@ def extendable_col(matrix, ecol, srow, erow): return False return True + # helper function to get the maximum covered rectangular area def area_helper(matrix, num_rows, num_cols, srow, erow, scol, ecol): # getting the current area @@ -34,23 +36,28 @@ def area_helper(matrix, num_rows, num_cols, srow, erow, scol, ecol): ex_row = erow < num_rows and extendable_row(matrix, erow, scol, ecol) # getting the row extended area - if (ex_row): - row_ex_area = area_helper(matrix, num_rows, num_cols,srow, erow+1, scol, ecol) + if ex_row: + row_ex_area = area_helper( + matrix, num_rows, num_cols, srow, erow + 1, scol, ecol + ) # checking if the columns considered can be extended ex_col = ecol < num_cols and extendable_col(matrix, ecol, srow, erow) # getting the column extended area - if (ex_col): - col_ex_area = area_helper(matrix, num_rows, num_cols,srow, erow, scol, ecol+1) + if ex_col: + col_ex_area = area_helper( + matrix, num_rows, num_cols, srow, erow, scol, ecol + 1 + ) # returning the maximum area return max(current_area, row_ex_area, col_ex_area) + # FUNCTION TO PERFORM THE OPERATION def get_max_rect(matrix): # if the matrix is empty 0 is returned - if (not matrix): + if not matrix: return 0 # max_area stores the area of the largest rectangle @@ -66,47 +73,30 @@ def get_max_rect(matrix): upper_bound_area = (num_rows - i) * (num_cols - j) # if the current position contains 1 and the upper bound on area is larger than the max area - if (matrix[i][j] and upper_bound_area > max_area): + if matrix[i][j] and upper_bound_area > max_area: # the maximum rectangular area covered the current and neighbouring elements is calculated - area = area_helper(matrix, num_rows, num_cols, i, i+1, j, j+1) + area = area_helper(matrix, num_rows, num_cols, i, i + 1, j, j + 1) # max_area is updated according to need max_area = max(area, max_area) return max_area + # DRIVER CODE -matrix = [[1, 0, 0, 0], - [1, 0, 1, 1], - [1, 0, 1, 1], - [0, 1, 0, 0]] +matrix = [[1, 0, 0, 0], [1, 0, 1, 1], [1, 0, 1, 1], [0, 1, 0, 0]] print(get_max_rect(matrix)) -matrix = [[1, 0, 0, 0], - [1, 0, 1, 1], - [1, 0, 1, 1], - [0, 1, 1, 1]] +matrix = [[1, 0, 0, 0], [1, 0, 1, 1], [1, 0, 1, 1], [0, 1, 1, 1]] print(get_max_rect(matrix)) -matrix = [[1, 1, 1, 1], - [1, 1, 1, 1], - [1, 1, 1, 1], - [1, 1, 1, 1]] +matrix = [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]] print(get_max_rect(matrix)) -matrix = [[0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0], - [0, 0, 0, 0]] +matrix = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] print(get_max_rect(matrix)) -matrix = [[1, 1, 1, 1], - [1, 1, 1, 1], - [1, 1, 0, 0], - [0, 0, 0, 0]] +matrix = [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 0, 0], [0, 0, 0, 0]] print(get_max_rect(matrix)) -matrix = [[1, 1, 0, 0], - [1, 0, 0, 0], - [1, 0, 0, 0], - [1, 0, 0, 0]] -print(get_max_rect(matrix)) \ No newline at end of file +matrix = [[1, 1, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]] +print(get_max_rect(matrix)) diff --git a/Solutions/137.py b/Solutions/137.py index d2bbd8c..baebd96 100644 --- a/Solutions/137.py +++ b/Solutions/137.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement a bit array. @@ -6,54 +6,55 @@ * init(size): initialize the array with size * set(i, val): updates index at i with val where val is either 1 or 0. * get(i): gets the value at index i. -''' +""" # Bit Array class -class Bit_Array(): +class Bit_Array: # initialize function def __init__(self, length): # storing the length of the array and the indices where the element is 1 self.length = length self.indices = set() - + # function to set the value of i'th position of the bit array def set(self, pos, val): # if the given position is out of the array, IndexError is raised - if (pos >= self.length): + if pos >= self.length: raise IndexError("Index is out of range") - # if the value is 1, its added to the index set + # if the value is 1, its added to the index set # (as duplicates are not allowed in hash list, even if the value is present, there is no problem) - if (val): + if val: self.indices.add(pos) # if the value is 0, if the element at the position was 1, the position removed from the index set else: - if (pos in self.indices): + if pos in self.indices: self.indices.remove(pos) - + def get(self, pos): # if the given position is out of the array, IndexError is raised - if (pos >= self.length): + if pos >= self.length: raise IndexError("Index is out of range") # returning the value based on whether the position is present in the index list - if (pos in self.indices): + if pos in self.indices: return 1 else: return 0 - + # function to display the array def __str__(self): res = [] for pos in range(self.length): - if (pos in self.indices): + if pos in self.indices: res.append(1) else: res.append(0) - + return str(res) + # DRIVER CODE arr = Bit_Array(8) @@ -65,4 +66,4 @@ def __str__(self): print(arr) print(arr.get(1)) -print(arr.get(4)) \ No newline at end of file +print(arr.get(4)) diff --git a/Solutions/138.py b/Solutions/138.py index ae11094..00e35ea 100644 --- a/Solutions/138.py +++ b/Solutions/138.py @@ -1,4 +1,4 @@ -''' +""" Problem: Find the minimum number of coins required to make n cents. @@ -8,7 +8,7 @@ Input = 16 Output = 3 (10¢, a 5¢, and a 1¢) -''' +""" # FUNCTION TO PERFORM THE OPERATION def calc_num_coins(target, amt_arr=[1, 5, 10, 25]): @@ -19,23 +19,24 @@ def calc_num_coins(target, amt_arr=[1, 5, 10, 25]): count = 0 # checking all the coins in the amount array - for i in range(length-1, -1, -1): + for i in range(length - 1, -1, -1): # adding the number of current coins that can be used optimally - count += (target // amt_arr[i]) + count += target // amt_arr[i] # updating target target = target % amt_arr[i] # breaking out of the loop if we have reached the target - if (target == 0): + if target == 0: break - + # returning the number of coins or raising ValueError if the target cannot be reached - if (target == 0): + if target == 0: return count else: raise ValueError("Target cannot be reached by using the supplied denominations") + # DRIVER CODE print(calc_num_coins(16)) print(calc_num_coins(90)) print(calc_num_coins(93)) -print(calc_num_coins(100)) \ No newline at end of file +print(calc_num_coins(100)) diff --git a/Solutions/139.py b/Solutions/139.py index 401919b..8797596 100644 --- a/Solutions/139.py +++ b/Solutions/139.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an iterator with methods next() and hasNext(), create a wrapper iterator, PeekableInterface, which also implements peek(). @@ -17,7 +17,7 @@ def next(self): def hasNext(self): pass -''' +""" # PeekableInterface class PeekableInterface(object): @@ -38,7 +38,7 @@ def peek(self): def next(self): # checking if the iterator has values - if (self.has_next): + if self.has_next: # storing the next value in a temporary variable temp = self.next_val try: @@ -59,6 +59,7 @@ def hasNext(self): # returning has_next return self.has_next + # DRIVER CODE sample_list = [1, 2, 3, 4, 5] iterator = iter(sample_list) @@ -89,4 +90,4 @@ def hasNext(self): peekable = PeekableInterface(iterator) print(peekable.peek()) -print(peekable.hasNext()) \ No newline at end of file +print(peekable.hasNext()) diff --git a/Solutions/14.py b/Solutions/14.py index d6f8783..a3378ec 100644 --- a/Solutions/14.py +++ b/Solutions/14.py @@ -1,9 +1,9 @@ -''' +""" Problem: The area of a circle is defined as πr^2. Estimate π to 3 decimal places using a Monte Carlo method. Hint: The basic equation of a circle is x2 + y2 = r2. -''' +""" # Library import (generate random numbers in [0, 1)) from random import random @@ -12,6 +12,7 @@ def coordinate_gen(): return (random(), random()) + # FUNCTION TO PERFORM THE OPERATION def pi_approx(iterations=1000000): # Circle area represents the number of points inside the circle @@ -21,12 +22,13 @@ def pi_approx(iterations=1000000): for _ in range(iterations): coordinate = coordinate_gen() - if ((coordinate[0] ** 2 + coordinate[1] ** 2) <= 1): + if (coordinate[0] ** 2 + coordinate[1] ** 2) <= 1: circle_area += 1 - - # Using Monte Carlo approximation (pi = 4 x (Area of circle / Area of square)) + + # Using Monte Carlo approximation (pi = 4 x (Area of circle / Area of square)) # [Area of circle = number of pts in circle, Area of square = total number of points] - return (4*circle_area/iterations) + return 4 * circle_area / iterations + # DRIVER CODE -print("{:.3f}".format(pi_approx())) \ No newline at end of file +print("{:.3f}".format(pi_approx())) diff --git a/Solutions/140.py b/Solutions/140.py index 7330dba..0e5e7db 100644 --- a/Solutions/140.py +++ b/Solutions/140.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an array of integers in which two elements appear exactly once and all other elements appear exactly twice. @@ -9,38 +9,39 @@ Input = [2, 4, 6, 8, 10, 2, 6, 10] Output = 4, 8 (The order does not matter) -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_uniques(arr): # checking if the array has at least 2 elements - if (len(arr) >= 2): + if len(arr) >= 2: # getting the xor of all the values xor_res = 0 for val in arr: xor_res = xor_res ^ val - + # getting the rightmost rest bit (as at least 1 bit needs to differ for 2 numbers to be different) rightmost_set_bit = xor_res & ~(xor_res - 1) num1 = 0 num2 = 0 - # using the rightmost set bit as mask to segregate the array of numbers into 2 sets + # using the rightmost set bit as mask to segregate the array of numbers into 2 sets # performing xor for num1 and num2 based on the set to which they belong to # the 2 sets are based on whether a number has rightmost_set_bit 1 or 0 for val in arr: - if (val & rightmost_set_bit): + if val & rightmost_set_bit: num1 = num1 ^ val else: num2 = num2 ^ val - + return num1, num2 - + # if the array is empty or contains 1 element, 2 'None's are returned else: return None, None + # DRIVER CODE print(get_uniques([2, 4, 6, 8, 10, 2, 6, 10])) -print(get_uniques([2, 4, 8, 8, 10, 2, 6, 10])) \ No newline at end of file +print(get_uniques([2, 4, 8, 8, 10, 2, 6, 10])) diff --git a/Solutions/141.py b/Solutions/141.py index 643fea6..067f5a4 100644 --- a/Solutions/141.py +++ b/Solutions/141.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement 3 stacks using a single list: @@ -11,7 +11,7 @@ def pop(self, stack_number): def push(self, item, stack_number): pass -''' +""" # stack class class Stack: @@ -27,28 +27,28 @@ def __init__(self): # pop function def pop(self, stack_number): - if (stack_number == 1): + if stack_number == 1: # calculating the length and checking for underflow - if (len(self.list[:self.pos1]) == 0): + if len(self.list[: self.pos1]) == 0: raise ValueError("Stack Underflow") # getting the necessary value - self.list.pop(self.pos1-1) + self.list.pop(self.pos1 - 1) # updating the position markers self.pos1 -= 1 self.pos2 -= 1 self.pos3 -= 1 - elif (stack_number == 2): + elif stack_number == 2: # calculating the length and checking for underflow - if (len(self.list[self.pos1:self.pos2]) == 0): + if len(self.list[self.pos1 : self.pos2]) == 0: raise ValueError("Stack Underflow") # getting the necessary value - self.list.pop(self.pos2-1) + self.list.pop(self.pos2 - 1) # updating the position markers self.pos2 -= 1 self.pos3 -= 1 else: # calculating the length and checking for underflow - if (len(self.list[self.pos2:]) == 0): + if len(self.list[self.pos2 :]) == 0: raise ValueError("Stack Underflow") # getting the necessary value self.list.pop() @@ -57,14 +57,14 @@ def pop(self, stack_number): # push function def push(self, item, stack_number): - if (stack_number == 1): + if stack_number == 1: # adding the value to the list self.list.insert(self.pos1, item) # updating the position markers self.pos1 += 1 self.pos2 += 1 self.pos3 += 1 - elif (stack_number == 2): + elif stack_number == 2: # adding the value to the list self.list.insert(self.pos2, item) # updating the position markers @@ -75,11 +75,12 @@ def push(self, item, stack_number): self.list.insert(self.pos3, item) # updating the position markers self.pos3 += 1 - + # string function def __str__(self): return f"Stack1: {self.list[:self.pos1]}\nStack2: {self.list[self.pos1:self.pos2]}\nStack3: {self.list[self.pos2:]}" + # DRIVER CODE stack = Stack() stack.push(5, 3) @@ -98,4 +99,4 @@ def __str__(self): stack.pop(1) stack.pop(3) -print(stack, "\n") \ No newline at end of file +print(stack, "\n") diff --git a/Solutions/142.py b/Solutions/142.py index 9e02513..8133d14 100644 --- a/Solutions/142.py +++ b/Solutions/142.py @@ -1,4 +1,4 @@ -''' +""" Problem: You're given a string consisting solely of (, ), and *. * can represent either a (, ), or an empty string. @@ -14,40 +14,45 @@ Input = )*( Output = not balanced -''' +""" # FUNCTION TO PERFORM THE OPERATION def can_balance(string, stack=None): # creating the stack if it has not been passed (1st call) - if (stack == None): + if stack == None: stack = [] - + # if both the string and stack are empty, the parenthesis is balanced (base case for recursion) - if (not string and not stack): + if not string and not stack: return True # if the string is empty and stack isn't, the parenthesis is not balanced (base case for recursion) - elif (not string): + elif not string: return False - + # if the 1st element is an opening parenthesis, its added to the stack and the function called recursively - if (string[0] == '('): - stack.append('(') + if string[0] == "(": + stack.append("(") return can_balance(string[1:], stack) - + # if the 1st element is an closing parenthesis, if the parenthesis can be balanced the function called recursively # else False is returned - elif (string[0] == ')'): - if (stack and stack[-1] == '('): + elif string[0] == ")": + if stack and stack[-1] == "(": stack.pop() return can_balance(string[1:], stack) else: return False - + # if the 1st element is '*', all the possible combinations are checked and if any of them can be balanced, True is returned - elif (string[0] == '*'): - return (can_balance('('+string[1:], list(stack)) or can_balance(')'+string[1:], list(stack)) or can_balance(string[1:], list(stack))) + elif string[0] == "*": + return ( + can_balance("(" + string[1:], list(stack)) + or can_balance(")" + string[1:], list(stack)) + or can_balance(string[1:], list(stack)) + ) + # DRIVER CODE -print(can_balance('(()*')) -print(can_balance('(*)')) -print(can_balance(')*(')) \ No newline at end of file +print(can_balance("(()*")) +print(can_balance("(*)")) +print(can_balance(")*(")) diff --git a/Solutions/143.py b/Solutions/143.py index 38ad876..d41902e 100644 --- a/Solutions/143.py +++ b/Solutions/143.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a pivot x, and a list lst, partition the list into three parts. @@ -10,47 +10,49 @@ Input = [9, 12, 3, 5, 14, 10, 10], 10 Output = [9, 3, 5, 10, 10, 12, 14] -''' +""" # helper function to perform the computation def separate_with_pivot(arr, i, j, x): # if the array is empty, no operation is performed - if (not arr): + if not arr: return # looping till i and j pointers cross - while (i < j): + while i < j: # if the left pointer has a value greater than or equal to x and right pointer has a value smaller than x # the values are swapped and pointers updated - if (arr[i] >= x and arr[j] < x): + if arr[i] >= x and arr[j] < x: arr[i], arr[j] = arr[j], arr[i] i += 1 j -= 1 # else updating the pointers as per requirements else: - if (arr[i] < x): + if arr[i] < x: i += 1 - if (arr[j] >= x): + if arr[j] >= x: j -= 1 # returning the position in the array containing a value greater than or equal to x - if ((arr[i] < x) and (i+1 < len(arr))): - return i + 1 + if (arr[i] < x) and (i + 1 < len(arr)): + return i + 1 else: return i + # FUNCTION TO PERFORM THE OPERATION def pivot_list(arr, x): # getting the length of the array length = len(arr) # getting the mid position (all elements to the left of mid is less than x), pushing all values smaller than x to the left - mid = separate_with_pivot(arr, 0, length-1, x) + mid = separate_with_pivot(arr, 0, length - 1, x) # pushing all values smaller than x+1 to the left (to get all the values equal to x clustered to the right of the smaller values) - separate_with_pivot(arr, mid, length-1, x+1) + separate_with_pivot(arr, mid, length - 1, x + 1) return arr + # DRIVER CODE print(pivot_list([9, 12, 3, 5, 14, 10, 10], 10)) print(pivot_list([9, 12, 3, 5, 14, 10, 10], 8)) @@ -58,4 +60,4 @@ def pivot_list(arr, x): print(pivot_list([9, 12, 14, 10, 10], 8)) print(pivot_list([3, 5], 8)) print(pivot_list([8, 8, 8], 8)) -print(pivot_list([], 8)) \ No newline at end of file +print(pivot_list([], 8)) diff --git a/Solutions/144.py b/Solutions/144.py index 8e97761..3d10b20 100644 --- a/Solutions/144.py +++ b/Solutions/144.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of numbers and an index i, return the index of the nearest larger number of the number at index i, where distance is measured in array indices. @@ -9,7 +9,7 @@ Input = [4, 1, 3, 5, 6], 0 Output = 3 -''' +""" # helper function to preprocess the data def preprocess(arr): @@ -21,10 +21,10 @@ def preprocess(arr): # sorting the index value tuple by value sorted_tuples = [(value, index) for index, value in enumerate(arr)] sorted_tuples.sort(key=lambda tup: tup[0]) - + # iterating through the sorted tuple for k, (_, i) in enumerate(sorted_tuples[:-1]): - # min_dist stores the minimum distance from the + # min_dist stores the minimum distance from the min_dist = length # iterating through the right side of the element (as the elements to the right are larger in a sorted array) @@ -32,27 +32,29 @@ def preprocess(arr): # getting the absolute distance dist_temp = abs(i - sorted_tuples[m][1]) # updating the distance as per requirement - if (dist_temp < min_dist): + if dist_temp < min_dist: min_dist = dist_temp preprocessed_indices[i] = sorted_tuples[m][1] # returning the preprocessed indices dictionary return preprocessed_indices + # FUNCTION TO PERFORM THE OPERATION def nearest_larger(arr, index): # preprocessing the data preprocessed_indices = preprocess(arr) # checking if the index is in the preprocessed_indices - if (index not in preprocessed_indices): + if index not in preprocessed_indices: return None # returning the proper index value return preprocessed_indices[index] + # DRIVER CODE print(nearest_larger([4, 1, 3, 5, 6], 0)) print(nearest_larger([4, 1, 3, 5, 6], 1)) print(nearest_larger([4, 1, 3, 5, 6], 4)) -print(nearest_larger([4, 1, 3, 5, 6], 3)) \ No newline at end of file +print(nearest_larger([4, 1, 3, 5, 6], 3)) diff --git a/Solutions/145.py b/Solutions/145.py index 1b2f682..074e605 100644 --- a/Solutions/145.py +++ b/Solutions/145.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given the head of a singly linked list, swap every two nodes and return its head. @@ -7,7 +7,7 @@ Input = 1 -> 2 -> 3 -> 4 Output = 2 -> 1 -> 4 -> 3 -''' +""" # local import from the Datastructure module from DataStructures.LinkedList import Node, Linked_list @@ -30,12 +30,13 @@ def swap_nodes(self): except: break - + # returning the head return self.head + # adding the swap_node function to Linked List -setattr(Linked_list, 'swap_nodes', swap_nodes) +setattr(Linked_list, "swap_nodes", swap_nodes) # DRIVER CODE LL = Linked_list() @@ -46,4 +47,4 @@ def swap_nodes(self): print(LL) -print(LL.swap_nodes()) \ No newline at end of file +print(LL.swap_nodes()) diff --git a/Solutions/146.py b/Solutions/146.py index 4c290c9..9093c9b 100644 --- a/Solutions/146.py +++ b/Solutions/146.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a binary tree where all nodes are either 0 or 1, prune the tree so that subtrees containing all 0s are removed. @@ -21,47 +21,49 @@ / 1 (We do not remove the tree at the root or its left child because it still has a 1 as a descendant.) -''' +""" # local import from the Datastructure module from DataStructures.Tree import Node, Binary_Tree # helper function to prune the tree def prune_helper(node): - # checking if the left node is present - if (node.left): - # pruning the left subtree - prune_helper(node.left) + # checking if the left node is present + if node.left: + # pruning the left subtree + prune_helper(node.left) - # checking if the value of the left child is 0 - if (node.left.val == 0): - # if the value is 0 and its a leaf node, the node is deleted - if (not node.left.left and not node.left.right): - temp = node.left - node.left = None - del temp - - # checking if the right node is present - if (node.right): - # pruning the right subtree - prune_helper(node.right) + # checking if the value of the left child is 0 + if node.left.val == 0: + # if the value is 0 and its a leaf node, the node is deleted + if not node.left.left and not node.left.right: + temp = node.left + node.left = None + del temp - # checking if the value of the right child is 0 - if (node.right.val == 0): - # if the value is 0 and its a leaf node, the node is deleted - if (not node.right.left and not node.right.right): - temp = node.right - node.right = None - del temp + # checking if the right node is present + if node.right: + # pruning the right subtree + prune_helper(node.right) -# FUNCTION TO PERFORM THE OPERATION + # checking if the value of the right child is 0 + if node.right.val == 0: + # if the value is 0 and its a leaf node, the node is deleted + if not node.right.left and not node.right.right: + temp = node.right + node.right = None + del temp + + +# FUNCTION TO PERFORM THE OPERATION def prune(tree): - # checking if the tree has values and calling the helper function - if (tree.root): - prune_helper(tree.root) - return tree - else: - return None + # checking if the tree has values and calling the helper function + if tree.root: + prune_helper(tree.root) + return tree + else: + return None + # DRIVER CODE tree = Binary_Tree() @@ -74,4 +76,4 @@ def prune(tree): tree.root.right.right = Node(0) print(tree) -print(prune(tree)) \ No newline at end of file +print(prune(tree)) diff --git a/Solutions/147.py b/Solutions/147.py index 64e628d..efa9c04 100644 --- a/Solutions/147.py +++ b/Solutions/147.py @@ -1,28 +1,30 @@ -''' +""" Problem: Given a list, sort it using this method: reverse(lst, i, j), which reverses lst from i to j. -''' +""" # reverse function implementation def reverse(lst, i, j): - lst[i:j+1] = lst[i:j+1][::-1] + lst[i : j + 1] = lst[i : j + 1][::-1] + # FUNCTION TO PERFORM THE OPERATION def sort(lst): # using basic bubble sort to sort the entire list length = len(lst) - for i in range(length-1): - for j in range(length-i-1): + for i in range(length - 1): + for j in range(length - i - 1): # reversing the items if the value at position j is larger than that at position i - if (lst[j] > lst[j+1]): - reverse(lst, j, j+1) - + if lst[j] > lst[j + 1]: + reverse(lst, j, j + 1) + return lst + # DRIVER CODE print(sort([0, 6, 4, 2, 5, 3, 1])) print(sort([0, 6, 4, 2, 5, 3, 1, 10, 9])) print(sort([0, 6, 4, 2, 5, 3, 1, 2, 3])) -print(sort([0, 6, 4, 2, 5, 3, 1, 11])) \ No newline at end of file +print(sort([0, 6, 4, 2, 5, 3, 1, 11])) diff --git a/Solutions/148.py b/Solutions/148.py index 8bbe7b2..22624da 100644 --- a/Solutions/148.py +++ b/Solutions/148.py @@ -1,4 +1,4 @@ -''' +""" Problem: Gray code is a binary code where each successive value differ in only one bit, as well as when wrapping around. @@ -9,27 +9,28 @@ Input = 2 Output = [00, 01, 11, 10] -''' +""" # FUNCTION TO PERFORM THE OPERATION def grey_code_gen(n): # if n is 0, a list with an empty string is returned (base case for recursion) - if (n == 0): - return [''] - + if n == 0: + return [""] + # getting the numbers for n-1 digits - get_prev_GC = grey_code_gen(n-1) + get_prev_GC = grey_code_gen(n - 1) # getting the numbers where the first digit is 0 and 1 respectively - base0 = ['0' + val for val in get_prev_GC] - base1 = ['1' + val for val in get_prev_GC[::-1]] + base0 = ["0" + val for val in get_prev_GC] + base1 = ["1" + val for val in get_prev_GC[::-1]] # returning the concatinated list return base0 + base1 + # DRIVER CODE print(grey_code_gen(0)) print(grey_code_gen(1)) print(grey_code_gen(2)) print(grey_code_gen(3)) -print(grey_code_gen(4)) \ No newline at end of file +print(grey_code_gen(4)) diff --git a/Solutions/149.py b/Solutions/149.py index cca8668..475f9aa 100644 --- a/Solutions/149.py +++ b/Solutions/149.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of numbers L, implement a method sum(i, j) which returns the sum from the sublist L[i:j] (including i, excluding j). @@ -9,30 +9,31 @@ Input = [1, 2, 3, 4, 5], 1, 3 Output = 5 (sum([2, 3])) -''' +""" # class to optimize the array and perform the sum over range class SubarraySumOptimizer: # default initialization function def __init__(self, arr): # creating a preprocessed array - self.preprocessed_arr = [0 for _ in range(len(arr)+1)] + self.preprocessed_arr = [0 for _ in range(len(arr) + 1)] # sum current stores the sum till the current element sum_curr = 0 # preprocessing the array for i in range(len(arr)): sum_curr += arr[i] - self.preprocessed_arr[i+1] = sum_curr + self.preprocessed_arr[i + 1] = sum_curr # FUNCTION TO PERFORM THE OPERATION def sum(self, start, end): # checking if the query is valid, returns 0 for invalid query - if ((start < 0) or (end > len(self.preprocessed_arr)-1) or (start > end)): + if (start < 0) or (end > len(self.preprocessed_arr) - 1) or (start > end): return 0 - + # returning the difference (as the array has been preprocessed) - return (self.preprocessed_arr[end] - self.preprocessed_arr[start]) + return self.preprocessed_arr[end] - self.preprocessed_arr[start] + # DRIVER CODE sso = SubarraySumOptimizer([1, 2, 3, 4, 5]) @@ -41,4 +42,4 @@ def sum(self, start, end): print(sso.sum(0, 5)) print(sso.sum(0, 4)) print(sso.sum(3, 4)) -print(sso.sum(3, 3)) \ No newline at end of file +print(sso.sum(3, 3)) diff --git a/Solutions/15.py b/Solutions/15.py index 3123bcb..ed255b9 100644 --- a/Solutions/15.py +++ b/Solutions/15.py @@ -1,12 +1,13 @@ -''' +""" Problem: Given a stream of elements too large to store in memory, pick a random element from the stream with uniform probability. -''' +""" # Library imports from random import random, randint -import matplotlib.pyplot as plt +import matplotlib.pyplot as plt + # note to use matplotlib, you need to have it installed (run cmd as admin and run 'pip install matplotlib') # Generator function to simulate a stream of elements too large to store in memory @@ -15,6 +16,7 @@ def generator(): rand_float = random() yield int(10000 * rand_float) + # FUNCTION TO PERFORM THE OPERATION def random_selector(): # using the generator function (created globally) @@ -22,15 +24,16 @@ def random_selector(): # an array to store 10 elements arr = [0 for i in range(10)] - + # generating 10 elements (equivalent to getting 10 elements from the stream of elements) for i in range(10): arr[i] = next(gen) - + # selecting a random element from the array of 10 elements pos = randint(0, 9) return arr[pos] + # DRIVER CODE # creating the generator gen = generator() @@ -44,4 +47,4 @@ def random_selector(): # plotting the histogram of frequencies of the elements plt.hist(check, edgecolor="black") -plt.show() \ No newline at end of file +plt.show() diff --git a/Solutions/150.py b/Solutions/150.py index 16ed8ed..22d2931 100644 --- a/Solutions/150.py +++ b/Solutions/150.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of points, a central point, and an integer k, find the nearest k points from the central point. @@ -7,21 +7,23 @@ Input = [(0, 0), (5, 4), (3, 1)], (1, 2), 2, Output = [(0, 0), (3, 1)] -''' +""" # helper function to calculate the distance def get_dist(point1, point2): # finding the distance using Pythagora's theorem return ((point1[0] - point2[0]) ** 2 + (point1[1] - point2[1]) ** 2) ** 0.5 + # FUNCTION TO PERFORM THE OPERATION def KNN(arr, center, k): # getting the points sorted by distance and returning the first k values return sorted(arr, key=lambda pt: get_dist(pt, center))[:k] + # DRIVER CODE arr = [(0, 0), (5, 4), (3, 1)] center = (1, 2) k = 2 -print(KNN(arr, center, k)) \ No newline at end of file +print(KNN(arr, center, k)) diff --git a/Solutions/151.py b/Solutions/151.py index b2f7aae..962cc31 100644 --- a/Solutions/151.py +++ b/Solutions/151.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given a 2-D matrix representing an image, a location of a pixel in the screen and a color C. @@ -17,7 +17,7 @@ G G G G G G B B B -''' +""" # importing array from numpy (its used to properly format the matrix while displaying, not a mandatory requirement) from numpy import array @@ -31,26 +31,27 @@ def gen_neighbours(pos, rows, cols): # getting all neighbours neighbours = [ - (i-1, j-1), - (i-1, j), - (i-1, j+1), - (i, j+1), - (i+1, j+1), - (i+1, j), - (i+1, j-1), - (i, j-1) + (i - 1, j - 1), + (i - 1, j), + (i - 1, j + 1), + (i, j + 1), + (i + 1, j + 1), + (i + 1, j), + (i + 1, j - 1), + (i, j - 1), ] # looping over neighbours and adding the valid neighbours to res for neighbour in neighbours: y, x = neighbour - if ((not (x >= cols) and not (x < 0)) and (not (y >= rows) and not (y < 0))): + if (not (x >= cols) and not (x < 0)) and (not (y >= rows) and not (y < 0)): res.append(neighbour) - + # returning res return res + # helper function to modify the matrix def dfs(mat, pos, new_color, prev_color, visited, rows, cols): # updating the color at the current position @@ -60,57 +61,44 @@ def dfs(mat, pos, new_color, prev_color, visited, rows, cols): # getting the neighbours neighbours = gen_neighbours(pos, rows, cols) - + # looping over neighbours for neighbour in neighbours: # checking if the color has to be modified for the given position and calling dfs as required - if (neighbour not in visited and mat[neighbour[0]][neighbour[1]] == prev_color): + if neighbour not in visited and mat[neighbour[0]][neighbour[1]] == prev_color: dfs(mat, neighbour, new_color, prev_color, visited, rows, cols) + # FUNCTION TO PERFORM THE OPERATION def update(mat, pos, new_color): # getting the rows and columns rows = len(mat) cols = len(mat[0]) - + # calling dfs the modify the matrix dfs(mat, pos, new_color, mat[pos[0]][pos[1]], set(), rows, cols) # returning the matrix return mat + # DRIVER CODE -print('Initial Matrix:') -mat = [ - ['B', 'B', 'W'], - ['W', 'W', 'W'], - ['W', 'W', 'W'], - ['B', 'B', 'B'] -] +print("Initial Matrix:") +mat = [["B", "B", "W"], ["W", "W", "W"], ["W", "W", "W"], ["B", "B", "B"]] print(array(mat)) -print('Updated Matrix:') -print(array(update(mat, (2, 2), 'G'))) +print("Updated Matrix:") +print(array(update(mat, (2, 2), "G"))) print() -print('Initial Matrix:') -mat = [ - ['B', 'B', 'W'], - ['W', 'W', 'W'], - ['W', 'W', 'W'], - ['B', 'B', 'B'] -] +print("Initial Matrix:") +mat = [["B", "B", "W"], ["W", "W", "W"], ["W", "W", "W"], ["B", "B", "B"]] print(array(mat)) -print('Updated Matrix:') -print(array(update(mat, (3, 2), 'G'))) +print("Updated Matrix:") +print(array(update(mat, (3, 2), "G"))) print() -print('Initial Matrix:') -mat = [ - ['B', 'B', 'W'], - ['W', 'W', 'W'], - ['W', 'W', 'W'], - ['B', 'B', 'B'] -] +print("Initial Matrix:") +mat = [["B", "B", "W"], ["W", "W", "W"], ["W", "W", "W"], ["B", "B", "B"]] print(array(mat)) -print('Updated Matrix:') -print(array(update(mat, (0, 0), 'G'))) \ No newline at end of file +print("Updated Matrix:") +print(array(update(mat, (0, 0), "G"))) diff --git a/Solutions/152.py b/Solutions/152.py index 119d9f6..32ab825 100644 --- a/Solutions/152.py +++ b/Solutions/152.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given n numbers as well as n probabilities that sum up to 1. @@ -9,11 +9,12 @@ Input = [1, 2, 3, 4], [0.1, 0.5, 0.2, 0.2] Output = your function should return 1 10% of the time, 2 50% of the time, and 3 and 4 20% of the time. -''' +""" from random import random import matplotlib.pyplot as plt + class RandomGenerator: def __init__(self, numbers, probabilities): self.numbers = numbers @@ -22,13 +23,14 @@ def __init__(self, numbers, probabilities): def generate(self): temp = random() cumulative = 0 - + for pos in range(len(self.probabilities)): cumulative += self.probabilities[pos] - if (cumulative >= temp): + if cumulative >= temp: return self.numbers[pos] + generator = RandomGenerator([1, 2, 3, 4], [0.1, 0.5, 0.2, 0.2]) res = [] @@ -36,4 +38,4 @@ def generate(self): res.append(generator.generate()) plt.hist(res) -plt.show() \ No newline at end of file +plt.show() diff --git a/Solutions/153.py b/Solutions/153.py index 5fedfda..4196d45 100644 --- a/Solutions/153.py +++ b/Solutions/153.py @@ -1,4 +1,4 @@ -''' +""" Problem: Find an efficient algorithm to find the smallest distance (measured in number of words) between any two given words in a string. @@ -7,7 +7,7 @@ Input = "hello", "world", "dog cat hello cat dog dog hello cat world" Output = 1 (as there's only one word "cat" in between the two words) -''' +""" # FUNCTION TO PERFORM THE OPERATION def dist_calc(text, word1, word2): @@ -23,13 +23,13 @@ def dist_calc(text, word1, word2): # iterating over the list of words for i in range(length): # if the current word is a match - if (word_list[i] == word1 or word_list[i] == word2): + if word_list[i] == word1 or word_list[i] == word2: # if the last has not been set, its updated along with pos - if (last == None): + if last == None: last = word_list[i] pos = i # if the same word is encountered again, pos is updated - elif (last == word_list[i]): + elif last == word_list[i]: pos = i else: # the last and pos values are updated and temp stores the current distance @@ -38,15 +38,16 @@ def dist_calc(text, word1, word2): pos = i # the minimum distance is stored in dist - if (dist == None): + if dist == None: dist = temp else: dist = min(dist, temp) - + return dist + # DRIVER CODE print(dist_calc("dog cat hello cat dog dog hello cat world", "hello", "world")) print(dist_calc("dog cat hello cat dog dog hello cat world", "world", "dog")) print(dist_calc("hello world", "hello", "world")) -print(dist_calc("hello", "hello", "world")) \ No newline at end of file +print(dist_calc("hello", "hello", "world")) diff --git a/Solutions/154.py b/Solutions/154.py index b894a4c..319333b 100644 --- a/Solutions/154.py +++ b/Solutions/154.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement a stack API using only a heap. A stack implements the following methods: @@ -8,7 +8,7 @@ Recall that a heap has the following operations: * push(item), which adds a new key to the heap * pop(), which removes and returns the max value of the heap -''' +""" # importing required functions and data from heapq import heappush, heappop @@ -20,17 +20,17 @@ class Stack: def __init__(self): self.heap = [] self.next_wt = maxsize - + # pop function def pop(self): # if the heap is empty, Value Error is raised - if (not self.heap): + if not self.heap: raise ValueError("Stack Underflow") # returning the required value _, val = heappop(self.heap) return val - + # push function def push(self, val): # adding the data to the heap as (weight, value) @@ -38,6 +38,7 @@ def push(self, val): # decerementing the next value as the heap functions are for min heap self.next_wt -= 1 + # DRIVER CODE stack = Stack() @@ -54,4 +55,4 @@ def push(self, val): print(stack.pop()) # Error -stack.pop() \ No newline at end of file +stack.pop() diff --git a/Solutions/155.py b/Solutions/155.py index e87b65b..529e187 100644 --- a/Solutions/155.py +++ b/Solutions/155.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of elements, find the majority element, which appears more than half the times (> floor(len(lst) / 2.0)). @@ -8,34 +8,35 @@ Input = [1, 2, 1, 1, 3, 4, 0] Output = 1 -''' +""" # FUNCTION TO PERFORM THE OPERATION def majority_element(arr): # getting the length length = len(arr) - + # returning the values based on length - if (not length): + if not length: return - elif (length < 3): + elif length < 3: return arr[0] - + # freq hash map to store the frequency of each element freq = {} # iterating through the array and generating freq for elem in arr: - if (elem in freq): + if elem in freq: freq[elem] += 1 else: freq[elem] = 1 - + # iterating through freq and finding the majority element for elem in freq: - if (freq[elem] > (length // 2)): + if freq[elem] > (length // 2): return elem + # DRIVER CODE print(majority_element([1, 2, 1, 1, 1, 4, 0])) -print(majority_element([1, 1, 1, 3, 3, 3, 4, 1, 1])) \ No newline at end of file +print(majority_element([1, 1, 1, 3, 3, 3, 4, 1, 1])) diff --git a/Solutions/156.py b/Solutions/156.py index ab5d91b..c565e26 100644 --- a/Solutions/156.py +++ b/Solutions/156.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a positive integer n, find the smallest number of squared integers which sum to n. @@ -10,16 +10,16 @@ Input = 27 Output = 3 (since 27 = 3^2 + 3^2 + 3^2 = 9 + 9 + 9) -''' +""" # FUNCTION TO PERFORM THE OPERATION def min_sq_num(num, accumulator=0): # base case for recursion 1 - if (num == 0): + if num == 0: return accumulator # base case for recursion 2 - elif (num == 1): - return (accumulator + 1) + elif num == 1: + return accumulator + 1 else: # getting the largest square number that is smaller than the current number @@ -32,7 +32,8 @@ def min_sq_num(num, accumulator=0): # calling the function recursively return min_sq_num(num, accumulator) + # DRIVER CODE -print(min_sq_num(25)) # (5 ^ 2) -print(min_sq_num(13)) # (2 ^ 2) + (3 ^ 2) -print(min_sq_num(27)) # (5 ^ 2) + (1 ^ 2) + (1 ^ 2) \ No newline at end of file +print(min_sq_num(25)) # (5 ^ 2) +print(min_sq_num(13)) # (2 ^ 2) + (3 ^ 2) +print(min_sq_num(27)) # (5 ^ 2) + (1 ^ 2) + (1 ^ 2) diff --git a/Solutions/157.py b/Solutions/157.py index 5f974f2..52d06a9 100644 --- a/Solutions/157.py +++ b/Solutions/157.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string, determine whether any permutation of it is a palindrome. @@ -10,7 +10,7 @@ Input = daily Output = false (since there's no rearrangement that can form a palindrome) -''' +""" # FUNCTION TO PERFORM THE OPERATION def palindrome_permutation(string): @@ -20,21 +20,22 @@ def palindrome_permutation(string): # iterating through the string for char in string: # deleting the charater upon encountering it again - if (char in char_set): + if char in char_set: char_set.remove(char) # adding the character to the set if its not present in the set else: char_set.add(char) - + # getting the number of elements in char_set length = len(char_set) # if the number of elements is 0 or 1, a palindrome permutation is possible - if (length == 1 or length == 0): + if length == 1 or length == 0: return True else: return False + # DRIVER CODE print(palindrome_permutation("carrace")) -print(palindrome_permutation("daily")) \ No newline at end of file +print(palindrome_permutation("daily")) diff --git a/Solutions/158.py b/Solutions/158.py index 3090fc2..cda1d06 100644 --- a/Solutions/158.py +++ b/Solutions/158.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an N * M matrix of 0s and 1s. Starting from the top left corner, how many ways are there to reach the bottom right corner? @@ -14,7 +14,7 @@ * Right, down, down, right * Down, right, down, right The top left corner and bottom right corner will always be 0.) -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_possible_paths(mat): @@ -24,63 +24,54 @@ def get_possible_paths(mat): # resetting the values of 1 to -1 as positive numbers are used to construct the paths for i in range(n): for j in range(m): - if (mat[i][j] == 1): + if mat[i][j] == 1: mat[i][j] = -1 - + # setting each element of the vertically down path as 1 (until a wall or the end is encountered) for i in range(n): - if (mat[i][0] == -1): + if mat[i][0] == -1: break else: mat[i][0] = 1 - + # setting each element of the horizontal (right-side) path as 1 (until a wall or the end is encountered) for i in range(m): - if (mat[0][i] == -1): + if mat[0][i] == -1: break else: mat[0][i] = 1 - + # iterating through the matrix, updating the paths for i in range(1, n): for j in range(1, m): # if the current position is not a wall, the value is updated - if (mat[i][j] != -1): + if mat[i][j] != -1: # res stores how many ways the current position can be reached res = 0 # updating the values based on whether it is a wall - if (mat[i-1][j] != -1): - res += mat[i-1][j] - if (mat[i][j-1] != -1): - res += mat[i][j-1] - + if mat[i - 1][j] != -1: + res += mat[i - 1][j] + if mat[i][j - 1] != -1: + res += mat[i][j - 1] + # storing the value in the matrix mat[i][j] = res - + # returning the required value return mat[-1][-1] + # DRIVER CODE -matrix = [[0, 0, 1], - [0, 0, 1], - [1, 0, 0]] +matrix = [[0, 0, 1], [0, 0, 1], [1, 0, 0]] print(get_possible_paths(matrix)) -matrix = [[0, 0, 1], - [1, 0, 1], - [1, 0, 0]] +matrix = [[0, 0, 1], [1, 0, 1], [1, 0, 0]] print(get_possible_paths(matrix)) -matrix = [[0, 0, 0], - [1, 0, 0], - [0, 0, 0]] +matrix = [[0, 0, 0], [1, 0, 0], [0, 0, 0]] print(get_possible_paths(matrix)) # end cannot be reached as only right and down traversal is allowed -matrix = [[0, 0, 0], - [1, 1, 0], - [0, 0, 0], - [0, 1, 1], - [0, 0, 0]] -print(get_possible_paths(matrix)) \ No newline at end of file +matrix = [[0, 0, 0], [1, 1, 0], [0, 0, 0], [0, 1, 1], [0, 0, 0]] +print(get_possible_paths(matrix)) diff --git a/Solutions/159.py b/Solutions/159.py index 0cb49b8..02569db 100644 --- a/Solutions/159.py +++ b/Solutions/159.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string, return the first recurring character in it, or null if there is no recurring chracter. @@ -10,7 +10,7 @@ Input = "abcdef" Output = null -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_first_recurring(string): @@ -20,15 +20,16 @@ def get_first_recurring(string): # iterating through the string for char in string: # if a previously seen character is encountered, its returned - if (char in seen): + if char in seen: return char - + # the current character is added to the set seen.add(char) # if there is no recurring character, None is returned return None + # DRIVER CODE print(get_first_recurring("acbbac")) -print(get_first_recurring("abcdef")) \ No newline at end of file +print(get_first_recurring("abcdef")) diff --git a/Solutions/16.py b/Solutions/16.py index 3733caa..b5c70a2 100644 --- a/Solutions/16.py +++ b/Solutions/16.py @@ -1,4 +1,4 @@ -''' +""" Problem: You run an e-commerce website and want to record the last N order ids in a log. @@ -8,17 +8,17 @@ * get_last(i): gets the ith last element from the log. i is guaranteed to be smaller than or equal to N. You should be as efficient with time and space -''' +""" # Object to store the necessary details -class Order_Log(): +class Order_Log: # Initialization def __init__(self, length): - # Circular buffer to hold the order ids + # Circular buffer to hold the order ids self.log_circular_buffer = [None for _ in range(length)] self.length = length self.pos = 0 - + # FUNCTION TO PERFORM THE OPERATION (record) def record(self, order_id): # Storing the order id and moving to the next index @@ -26,7 +26,7 @@ def record(self, order_id): self.pos += 1 # Returning to the start in case all logs are filled - if (self.pos == self.length): + if self.pos == self.length: self.pos = 0 # FUNCTION TO PERFORM THE OPERATION (get_last) @@ -34,9 +34,10 @@ def get_last(self, i): # Getting the position of the desired order id # Negative numbers won't be a problem as python supports negative indexing (in other languages, use i += length (if i < 0)) i = self.pos - i - + return self.log_circular_buffer[i] + # DRIVER CODE log = Order_Log(10) @@ -51,4 +52,4 @@ def get_last(self, i): log.record(21) print(log.get_last(1)) -print(log.get_last(3)) \ No newline at end of file +print(log.get_last(3)) diff --git a/Solutions/160.py b/Solutions/160.py index 401a4b5..078d789 100644 --- a/Solutions/160.py +++ b/Solutions/160.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a tree where each edge has a weight, compute the length of the longest path in the tree. @@ -16,7 +16,7 @@ g h weights: a-b: 3, a-c: 5, a-d: 8, d-e: 2, d-f: 4, e-g: 1, e-h: 1 Output = 17 (the longest path would be c -> a -> d -> f, with a length of 17) -''' +""" # Node class class Node: @@ -25,17 +25,17 @@ def __init__(self, val): self.val = val self.max_path = 0 self.child_dists = {} - + # function to add a child to a node def add_children(self, child, wt): self.child_dists[child] = wt - + # function to get the max path (works only after updating the paths) def get_max_path(self, tree): # if the current node is a leaf, 0 is returned - if (not self.child_dists): + if not self.child_dists: return 0 - + # path_lengths store the max path length for the current node # children_max_path_lengths store the max path length for the current node's children path_lengths = [] @@ -45,14 +45,14 @@ def get_max_path(self, tree): for node, dist in self.child_dists.items(): path_lengths.append(tree.tree[node].max_path + dist) children_max_path_lengths.append(tree.tree[node].get_max_path(tree)) - + # returning the result return max(sum(sorted(path_lengths)[-2:]), max(children_max_path_lengths)) - + # function to update the paths def update_max_paths(self, tree): # max_path is set to 0 if the node has no children - if (not self.child_dists): + if not self.child_dists: self.max_path = 0 return @@ -67,6 +67,7 @@ def update_max_paths(self, tree): # storing the maximum root path self.max_path = max(root_paths) + # Tree class class Tree: # initialization function @@ -79,38 +80,39 @@ def add_Node(self, val): self.tree[val] = Node(val) # incase the tree was empty, the passed node is stored as the root - if (not self.root): + if not self.root: self.root = val - + # add child function def add_child(self, parent, child, wt): # if the parent is absent ValueError is raised - if (parent not in self.tree): + if parent not in self.tree: raise ValueError("Parent Node not present in the tree") - + # the tree is created like a graph (with adjacency list) self.tree[parent].add_children(child, wt) self.tree[child] = Node(child) - - # get_longest_path function, updates the paths and calls get_max_path on root + + # get_longest_path function, updates the paths and calls get_max_path on root # NOTE: if multiple times max path is run on the same tree, updating the paths once would suffice def get_longest_path(self): - if (not self.root): + if not self.root: return 0 - + self.tree[self.root].update_max_paths(self) return self.tree[self.root].get_max_path(self) + # DRIVER CODE tree = Tree() -tree.add_Node('a') -tree.add_child('a', 'b', 3) -tree.add_child('a', 'c', 5) -tree.add_child('a', 'd', 8) -tree.add_child('d', 'e', 2) -tree.add_child('d', 'f', 4) -tree.add_child('e', 'g', 1) -tree.add_child('e', 'h', 1) +tree.add_Node("a") +tree.add_child("a", "b", 3) +tree.add_child("a", "c", 5) +tree.add_child("a", "d", 8) +tree.add_child("d", "e", 2) +tree.add_child("d", "f", 4) +tree.add_child("e", "g", 1) +tree.add_child("e", "h", 1) -print(tree.get_longest_path()) \ No newline at end of file +print(tree.get_longest_path()) diff --git a/Solutions/161.py b/Solutions/161.py index 1b16e4e..630b415 100644 --- a/Solutions/161.py +++ b/Solutions/161.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a 32-bit integer, return the number with its bits reversed. @@ -7,7 +7,7 @@ Input = 1111 0000 1111 0000 1111 0000 1111 0000 Output = 0000 1111 0000 1111 0000 1111 0000 1111 -''' +""" # FUNCTION TO PERFORM THE OPERATION def complement_1s(num): @@ -18,9 +18,10 @@ def complement_1s(num): for i in num: # inverting the number and adding it to the result res += str(int(not int(i))) - + # returning the result return res + # DRIVER CODE -print(complement_1s("11110000111100001111000011110000")) \ No newline at end of file +print(complement_1s("11110000111100001111000011110000")) diff --git a/Solutions/162.py b/Solutions/162.py index 5acb45c..eaea69b 100644 --- a/Solutions/162.py +++ b/Solutions/162.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of words, return the shortest unique prefix of each word. @@ -7,7 +7,7 @@ Input = ["dog", "cat", "apple", "apricot", "fish"] Output = ["d", "c", "app", "apr", "f"] -''' +""" # helper function to get the unique prefix for the current word def get_unique(dictionary, string, string_list): @@ -20,7 +20,7 @@ def get_unique(dictionary, string, string_list): prefix += char # if the prefix doesn't exist in the dictionary, its returned - if (prefix not in dictionary): + if prefix not in dictionary: return prefix else: # if the prefix exists, the prefix of the word which collided with the current prefix is updated @@ -33,14 +33,15 @@ def get_unique(dictionary, string, string_list): del dictionary[prefix] try: - temp_pre = temp_str[:len(temp_pre)+1] + temp_pre = temp_str[: len(temp_pre) + 1] except: return None dictionary[temp_pre] = temp_pos - + return None + # FUNCTION TO PERFORM THE OPERATION def unique_prefix(string_list): # dictionary maps the prefix to the index of the word @@ -52,14 +53,15 @@ def unique_prefix(string_list): prefix = get_unique(dictionary, string, string_list) # if unique prefix doesn't exist, ValueError is raised - if (not prefix): + if not prefix: raise ValueError("Unique Prefix Generation not possible") # the prefix is updated in the dictionary dictionary[prefix] = index - + # returning the list of prefixes return list(dictionary.keys()) + # DRIVER CODE -print(unique_prefix(['dog', 'cat', 'apple', 'apricot', 'fish'])) \ No newline at end of file +print(unique_prefix(["dog", "cat", "apple", "apricot", "fish"])) diff --git a/Solutions/163.py b/Solutions/163.py index 3839216..d6e511e 100644 --- a/Solutions/163.py +++ b/Solutions/163.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an arithmetic expression in Reverse Polish Notation, write a program to evaluate it. @@ -12,14 +12,14 @@ Input = [15, 7, 1, 1, '+', '-', '/', 3, '*', 2, 1, 1, '+', '+', '-'] Output = 5 [((15 / (7 - (1 + 1))) * 3) - (2 + (1 + 1))] -''' +""" # acceptable functions FUNCTIONS = { - '+': lambda a, b: a + b, - '-': lambda a, b: a - b, - '*': lambda a, b: a * b, - '/': lambda a, b: a / b # use // instead of / for integer division + "+": lambda a, b: a + b, + "-": lambda a, b: a - b, + "*": lambda a, b: a * b, + "/": lambda a, b: a / b, # use // instead of / for integer division } # FUNCTION TO PERFORM THE OPERATION @@ -32,17 +32,18 @@ def calculate(expression_list): # iterating through the expressions list for expression in expression_list: # if the expression is an operation, the operation is performed and the result added to the stack - if (expression in FUNCTIONS): + if expression in FUNCTIONS: a = stack.pop() b = stack.pop() stack.append(FUNCTIONS[expression](a, b)) # if the expression is an operand, its added to the stack else: stack.append(expression) - + # returning the final result return stack[0] + # DRIVER CODE -print(calculate([5, 3, '+'])) -print(calculate([15, 7, 1, 1, '+', '-', '/', 3, '*', 2, 1, 1, '+', '+', '-'])) \ No newline at end of file +print(calculate([5, 3, "+"])) +print(calculate([15, 7, 1, 1, "+", "-", "/", 3, "*", 2, 1, 1, "+", "+", "-"])) diff --git a/Solutions/164.py b/Solutions/164.py index 4747f4b..51d06ed 100644 --- a/Solutions/164.py +++ b/Solutions/164.py @@ -1,10 +1,10 @@ -''' +""" Problem: You are given an array of length n + 1 whose elements belong to the set {1, 2, ..., n}. By the pigeonhole principle, there must be a duplicate. Find it in linear time and space. -''' +""" # FUNCTION TO PERFORM THE OPERATION def find_duplicate(arr): @@ -14,10 +14,11 @@ def find_duplicate(arr): # iterating through the array and populating seen for i in arr: # when a previously seen element is encountered again, its returned - if (i in seen): + if i in seen: return i seen.add(i) + # DRIVER CODE print(find_duplicate([1, 2, 4, 6, 5, 3, 2])) -print(find_duplicate([3, 1, 4, 2, 3])) \ No newline at end of file +print(find_duplicate([3, 1, 4, 2, 3])) diff --git a/Solutions/165.py b/Solutions/165.py index 676b459..a399dc0 100644 --- a/Solutions/165.py +++ b/Solutions/165.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of integers, return a new array where each element in the new array is the number of smaller elements to the right of that element in the original input array. @@ -15,7 +15,7 @@ * There is 1 smaller element to the right of 6 * There are no smaller elements to the right of 1 ) -''' +""" # FUNCTION TO PERFORM THE OPERATION def smaller_elem_arr_construct(arr): @@ -31,17 +31,18 @@ def smaller_elem_arr_construct(arr): smaller_elements = 0 # updating smaller_elements - for j in range(i+1, length): - if (arr[i] > arr[j]): + for j in range(i + 1, length): + if arr[i] > arr[j]: smaller_elements += 1 - + # updating smaller_arr small_arr.append(smaller_elements) - + # returning the resultant array return small_arr + # DRIVER CODE print(smaller_elem_arr_construct([3, 4, 9, 6, 1])) -# NOTE: This problem can be solved in O(nlogn) using AVL Tree, but the algorithm is complex to understand \ No newline at end of file +# NOTE: This problem can be solved in O(nlogn) using AVL Tree, but the algorithm is complex to understand diff --git a/Solutions/166.py b/Solutions/166.py index 8c60c37..5a0156e 100644 --- a/Solutions/166.py +++ b/Solutions/166.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement a 2D iterator class. It will be initialized with an array of arrays, and should implement the following methods: @@ -10,7 +10,7 @@ Input = [[1, 2], [3], [], [4, 5, 6]] Output = 1, 2, 3, 4, 5, 6 (calling next() repeatedly should output this sequence) -''' +""" # iterator class class iterator: @@ -30,12 +30,12 @@ def generator_func(self, matrix): # string function to display the matrix def __str__(self): return str(self.mat) - + # has next function implementation def has_next(self): # checking if the elements are left in the iterator - return (self.next_value != None) - + return self.next_value != None + # next function implementation def next(self): # storing the next value for returning @@ -46,10 +46,11 @@ def next(self): self.next_value = next(self.generator) except StopIteration: self.next_value = None - + # returning the stored value return temp + # DRIVER CODE iter_obj = iterator([[1, 2], [3], [], [4, 5, 6]]) print(iter_obj) @@ -67,4 +68,4 @@ def next(self): print(iter_obj.has_next()) print(iter_obj.next()) print(iter_obj.has_next()) -print(iter_obj.next()) \ No newline at end of file +print(iter_obj.next()) diff --git a/Solutions/167.py b/Solutions/167.py index 1af7fce..a898811 100644 --- a/Solutions/167.py +++ b/Solutions/167.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of words, find all pairs of unique indices such that the concatenation of the two words is a palindrome. @@ -7,11 +7,12 @@ Input = ["code", "edoc", "da", "d"] Output = [(0, 1), (1, 0), (2, 3)] -''' +""" # functio to check if a string is palindrome def palindrome_check(string): - return (string == string[::-1]) + return string == string[::-1] + # FUNCTION TO PERFORM THE OPERATION def get_all_concatenated_palindrome(string_list): @@ -23,14 +24,15 @@ def get_all_concatenated_palindrome(string_list): # iterating through the array for i in range(length): # checking for all combinations (brute force) - for j in range(i+1, length): + for j in range(i + 1, length): # checking if the concatination yields a palindrome and adding the indices to the result array - if (palindrome_check(string_list[i] + string_list[j])): + if palindrome_check(string_list[i] + string_list[j]): res.append((i, j)) - if (palindrome_check(string_list[j] + string_list[i])): + if palindrome_check(string_list[j] + string_list[i]): res.append((j, i)) - + return res + # DRIVER CODE -print(get_all_concatenated_palindrome(["code", "edoc", "da", "d"])) \ No newline at end of file +print(get_all_concatenated_palindrome(["code", "edoc", "da", "d"])) diff --git a/Solutions/168.py b/Solutions/168.py index 2074c0b..41328d2 100644 --- a/Solutions/168.py +++ b/Solutions/168.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an N by N matrix, rotate it by 90 degrees clockwise. @@ -13,7 +13,7 @@ Output = [[7, 4, 1], [8, 5, 2], [9, 6, 3]] -''' +""" # numpy array to format the output from numpy import array @@ -28,9 +28,9 @@ def rotate_matrix(matrix): for layer in range(num_layers): for ind in range(layer, max_ind - layer): # rotate 4 numbers ( - # right col to bottom row, - # bottom row to left col, - # left col to top row, + # right col to bottom row, + # bottom row to left col, + # left col to top row, # top row to right col # ) temp = matrix[layer][ind] @@ -38,17 +38,13 @@ def rotate_matrix(matrix): matrix[max_ind - ind][layer] = matrix[max_ind - layer][max_ind - ind] matrix[max_ind - layer][max_ind - ind] = matrix[ind][max_ind - layer] matrix[ind][max_ind - layer] = temp - + return matrix + # DRIVER CODE -matrix = [[1, 2, 3], - [4, 5, 6], - [7, 8, 9]] +matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] print(array(rotate_matrix(matrix))) -matrix = [[1, 2, 3, 4], - [5, 6, 7, 8], - [9, 10, 11, 12], - [13, 14, 15, 16]] -print(array(rotate_matrix(matrix))) \ No newline at end of file +matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]] +print(array(rotate_matrix(matrix))) diff --git a/Solutions/169.py b/Solutions/169.py index f256778..033ebf8 100644 --- a/Solutions/169.py +++ b/Solutions/169.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a linked list, sort it in O(n log n) time and constant space. @@ -7,71 +7,74 @@ Input = 4 -> 1 -> -3 -> 99 Output = -3 -> 1 -> 4 -> 99 -''' +""" # importing from the local Datastructures module from DataStructures.LinkedList import Node, Linked_list # merge function -def sortedMerge(self, a, b): +def sortedMerge(self, a, b): # base cases (when either part becomes empty) - if (a == None): - return b - if (b == None): - return a - + if a == None: + return b + if b == None: + return a + result = None - + # pick either a or b (whichever smaller) and recursion to form the sorted list - if (a.val <= b.val): - result = a - result.next = self.sortedMerge(a.next, b) - else: - result = b - result.next = self.sortedMerge(a, b.next) - - return result + if a.val <= b.val: + result = a + result.next = self.sortedMerge(a.next, b) + else: + result = b + result.next = self.sortedMerge(a, b.next) + + return result + # merge sort function for the linked list def mergeSort(self, h): # Base case if head is None - if (h == None or h.next == None): + if h == None or h.next == None: return h - # get the middle of the list - middle = self.getMiddle(h) + # get the middle of the list + middle = self.getMiddle(h) nexttomiddle = middle.next - # set the next of middle node to None + # set the next of middle node to None middle.next = None - # apply mergeSort on left list - left = self.mergeSort(h) - - # apply mergeSort on right list - right = self.mergeSort(nexttomiddle) + # apply mergeSort on left list + left = self.mergeSort(h) + + # apply mergeSort on right list + right = self.mergeSort(nexttomiddle) + + # merge the left and right lists + sortedlist = self.sortedMerge(left, right) + return sortedlist + - # merge the left and right lists - sortedlist = self.sortedMerge(left, right) - return sortedlist - # utility function to get the middle of the linked list using fast pointer slow pointer -def getMiddle(self, head): +def getMiddle(self, head): # checking if the part is empty - if (head == None): - return head + if head == None: + return head # initializing the fast and slow pointers - slow = head - fast = head + slow = head + fast = head # finding the middle - while (fast.next != None and fast.next.next != None): + while fast.next != None and fast.next.next != None: slow = slow.next fast = fast.next.next - + # returning the middle - return slow + return slow + # sort function def sort(self): @@ -80,18 +83,19 @@ def sort(self): # updating the rear curr = self.head - while (curr.next): + while curr.next: curr = curr.next self.rear = curr # returning the linked list return self + # adding the necessary function to linked list class -setattr(Linked_list, 'sortedMerge', sortedMerge) -setattr(Linked_list, 'mergeSort', mergeSort) -setattr(Linked_list, 'getMiddle', getMiddle) -setattr(Linked_list, 'sort', sort) +setattr(Linked_list, "sortedMerge", sortedMerge) +setattr(Linked_list, "mergeSort", mergeSort) +setattr(Linked_list, "getMiddle", getMiddle) +setattr(Linked_list, "sort", sort) # DRIVER CODE LL = Linked_list() @@ -111,4 +115,4 @@ def sort(self): print(LL) LL.sort() -print(LL) \ No newline at end of file +print(LL) diff --git a/Solutions/17.py b/Solutions/17.py index 6e1c6fd..00b0891 100644 --- a/Solutions/17.py +++ b/Solutions/17.py @@ -1,4 +1,4 @@ -''' +""" Problem: Suppose we represent our file system by a string in the following manner: @@ -20,42 +20,48 @@ We are interested in finding the longest (number of characters) absolute path to a file within our file system. For example, in the second example above, the longest absolute path is "dir/subdir2/subsubdir2/file2.ext", and its length is 32 (not including the double quotes). Given a string representing the file system in the above format, return the length of the longest absolute path to a file in the abstracted file system. If there is no file in the system, return 0. -''' +""" # Function to count the number of tabs def count_tabs(string): - return string.count('\t') + return string.count("\t") + # FUNCTION TO PERFORM THE OPERATION def longest_dir(string): # Getting the required data from the given string - dir_list = string.split('\n') + dir_list = string.split("\n") length = len(dir_list) longest_directory_length = 0 longest_directory = "" # looping over the list of paths - for i in range(length-1, -1, -1): + for i in range(length - 1, -1, -1): # counting the number of tabs to check the location (0 tabs=parent, 1=sub-directory, 2=sub-sub-directory, ...) temp = dir_list[i] count = count_tabs(temp) - temp_dir = temp.lstrip('\t') + temp_dir = temp.lstrip("\t") # moving back through the list to recreate the entire directory (if it is a file: files have '.') - if (temp_dir.find('.') != -1): + if temp_dir.find(".") != -1: for j in range(i, -1, -1): - if (count_tabs(dir_list[j]) < count): - temp_dir = dir_list[j].lstrip('\t') + '/' + temp_dir + if count_tabs(dir_list[j]) < count: + temp_dir = dir_list[j].lstrip("\t") + "/" + temp_dir temp = dir_list[j] count = count_tabs(temp) - + # if the length of the generated is larger than the previously available longest_directory, details are overwritten - if (longest_directory_length < len(temp_dir)): + if longest_directory_length < len(temp_dir): longest_directory_length = len(temp_dir) longest_directory = temp_dir - + return longest_directory_length + # DRIVER CODE print(longest_dir("dir\n\tsubdir1\n\tsubdir2\n\t\tfile.ext")) -print(longest_dir("dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext")) \ No newline at end of file +print( + longest_dir( + "dir\n\tsubdir1\n\t\tfile1.ext\n\t\tsubsubdir1\n\tsubdir2\n\t\tsubsubdir2\n\t\t\tfile2.ext" + ) +) diff --git a/Solutions/170.py b/Solutions/170.py index 8ac92bd..ec62d69 100644 --- a/Solutions/170.py +++ b/Solutions/170.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given a start word, an end word, and a dictionary of valid words. @@ -16,7 +16,7 @@ end = "cat", dictionary = {"dot", "tod", "dat", "dar"} Output = null (as there is no possible transformation from dog to cat) -''' +""" # function to check if 2 strings differ by exactly 1 charcter def is_one_diff(s1, s2): @@ -26,69 +26,70 @@ def is_one_diff(s1, s2): # no_mismatch holds if there is no mismatch between the strings no_mismatch = True - # if the length difference is more than 1, flase is returned as they cannot differ by 1 - if (len1 != len2): - if (abs(len1 - len2) > 1): + # if the length difference is more than 1, flase is returned as they cannot differ by 1 + if len1 != len2: + if abs(len1 - len2) > 1: return False # if the length difference is 1, no_mismatch is nulled as a mismatch has occoured no_mismatch = False - + # iterating through each set of characters in the strings for c1, c2 in zip(s1, s2): # if there is a mismatch - if (c1 != c2): + if c1 != c2: # if there was no mismatch previously, no_mismatch is nulled - if (no_mismatch): + if no_mismatch: no_mismatch = False # else more than 1 mismatch has occoured and False is returned else: return False - + # if the strings are the same, False is returned - if (no_mismatch): + if no_mismatch: return False # if the 2 strings differ by exactly 1 charcter, True is returned return True + # undirected graph class class Graph: # initialization def __init__(self): self.nodes = {} - + # function to add a vertex def add_vert(self, vert): self.nodes[vert] = set() - + # function to add an edge between 2 vertices def add_edge(self, vert1, vert2): # adding the missing vertices - if (vert1 not in self.nodes): + if vert1 not in self.nodes: self.add_vert(vert1) - if (vert2 not in self.nodes): + if vert2 not in self.nodes: self.add_vert(vert2) # adding the edge self.nodes[vert1].add(vert2) self.nodes[vert2].add(vert1) - + # dfs function to generate a matrix containing all paths from the start word to the search word def dfs(self, current, search_elem, visited, sequence, holder_mat): # if the search element is reached, the sequence is added to the matrix - if (current == search_elem): + if current == search_elem: sequence.append(current) holder_mat.append(sequence) return - + # the current node is added to the visited set and the current sequence visited.add(current) sequence.append(current) # running dfs for unvisited nodes (recursively) for node in self.nodes[current]: - if (node not in visited): + if node not in visited: self.dfs(node, search_elem, set(visited), list(sequence), holder_mat) - + # creating the graph from a list of words def create(self, vert_list): # getting the length of the list @@ -97,13 +98,14 @@ def create(self, vert_list): # checking for every combination of words and adding an edge if they differ by 1 character for i in range(length): for j in range(i, length): - if (is_one_diff(vert_list[i], vert_list[j])): + if is_one_diff(vert_list[i], vert_list[j]): self.add_edge(vert_list[i], vert_list[j]) + # FUNCTION TO PERFORM THE OPERATION def min_transform(start, stop, dictionary): # adding the start to the dictionary incase its not present - if (start not in dictionary): + if start not in dictionary: dictionary.append(start) # creating the graph @@ -111,27 +113,28 @@ def min_transform(start, stop, dictionary): graph.create(dictionary) # creating the matrix to store the list of traversals - mat = [] + mat = [] # performing dfs on the graph graph.dfs(start, stop, set(), [], mat) # if the matrix is empty, there are no paths from the start to the stop words - if (not mat): + if not mat: return None - + # getting the shortest sequence from the matrix of sequences sequence = None length = 99999 - + for seq in mat: - if (len(seq) < length): + if len(seq) < length: sequence = seq length = len(seq) - + # returning the shortest sequence return sequence + # DRIVER CODE print(min_transform("dog", "cat", ["dot", "dop", "dat", "cat"])) -print(min_transform("dog", "cat", ["dot", "tod", "dat", "dar"])) \ No newline at end of file +print(min_transform("dog", "cat", ["dot", "tod", "dat", "dar"])) diff --git a/Solutions/171.py b/Solutions/171.py index c7815e9..6cb0cd4 100644 --- a/Solutions/171.py +++ b/Solutions/171.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given a list of data entries that represent entries and exits of groups of people into a building. @@ -14,7 +14,7 @@ Find the busiest period in the building, that is, the time with the most people in the building. Return it as a pair of (start, end) timestamps. You can assume the building always starts off and ends up empty, i.e. with 0 people inside. -''' +""" # FUNCTION TO PERFORM THE OPERATION def calc_busiest_time(list_of_events): @@ -38,48 +38,49 @@ def calc_busiest_time(list_of_events): count = event["count"] # checking the action (entry / exit) and getting the new number of people - if (event["type"] == "enter"): + if event["type"] == "enter": temp = dict_people_inside[last_pos] + count else: temp = dict_people_inside[last_pos] - count - + # updating the values in the dictionary last_pos = event["timestamp"] dict_people_inside[last_pos] = temp - + # creating a list from the dictionary [each element: (timestamp, people_inside)] temp_list = list(dict_people_inside.items()) - + # sorting the list (in reverse) by number of people inside and storing the timestamp of the busiest time temp_list.sort(reverse=True, key=lambda element: element[1]) start = temp_list[0][0] - + # sorting the list again by time stamp temp_list.sort(key=lambda element: element[0]) - + # flag stores if the next index is the end timestamp flag = False # iterating through the list of timestamp and people inside for timestamp, _ in temp_list: # if flag is set, the current timestamp is the end timestamp, the control breaks out of the loop - if (flag): + if flag: end = timestamp break # if the current timestamp is the start, flag is set - if (timestamp == start): + if timestamp == start: flag = True - + # returning the start and end return start, end + # DRIVER CODE events = [ {"timestamp": 1526579928, "count": 3, "type": "enter"}, {"timestamp": 1526579982, "count": 4, "type": "enter"}, {"timestamp": 1526580054, "count": 5, "type": "exit"}, {"timestamp": 1526580128, "count": 1, "type": "enter"}, - {"timestamp": 1526580382, "count": 3, "type": "exit"} + {"timestamp": 1526580382, "count": 3, "type": "exit"}, ] -print(calc_busiest_time(events)) \ No newline at end of file +print(calc_busiest_time(events)) diff --git a/Solutions/172.py b/Solutions/172.py index 638b7d8..16967c9 100644 --- a/Solutions/172.py +++ b/Solutions/172.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string s and a list of words words, where each word is the same length, find all starting indices of substrings in s that is a concatenation of every word in words exactly once. @@ -12,10 +12,11 @@ s = "barfoobazbitbyte" words = ["dog", "cat"] Output = [] (since there are no substrings composed of "dog" and "cat" in s) -''' +""" # importing permutation (generating all possible permutations) from itertools import permutations + # importing regex function from re import finditer @@ -29,12 +30,13 @@ def get_indices(s, words): # checking the occurance of every permutation using regex for permutation in permutation_list: res.extend([match.start() for match in finditer(permutation, s)]) - + # sorting the result and returning it - res.sort() + res.sort() return res + # DRIVER CODE print(get_indices("barfoobazbitbyte", ["dog", "cat"])) print(get_indices("dogcatcatcodecatdog", ["cat", "dog"])) -print(get_indices("dogcatcatcodecatdogcat", ["cat", "dog"])) \ No newline at end of file +print(get_indices("dogcatcatcodecatdogcat", ["cat", "dog"])) diff --git a/Solutions/173.py b/Solutions/173.py index ddaa7dd..3bb80e5 100644 --- a/Solutions/173.py +++ b/Solutions/173.py @@ -1,4 +1,4 @@ -''' +""" Problem: Write a function to flatten a nested dictionary. Namespace the keys with a period. @@ -21,7 +21,7 @@ "foo.a": 5, "foo.bar.baz": 8 } -''' +""" # FUNCTION TO PERFORM THE OPERATION def flatten_dict(dictionary): @@ -34,26 +34,19 @@ def flatten_dict(dictionary): temp = dictionary[key] # if the value is a dictionary - if (type(temp) == dict): + if type(temp) == dict: # its flattened recursively temp = flatten_dict(temp) - + # the value in the dictionary is deleted del dictionary[key] # the flatted dictionary is added to the parent dictionary using the convention "." for j in temp: dictionary[key + f".{j}"] = temp[j] - + return dictionary + # DRIVER CODE -print(flatten_dict({ - "key": 3, - "foo": { - "a": 5, - "bar": { - "baz": 8 - } - } -})) \ No newline at end of file +print(flatten_dict({"key": 3, "foo": {"a": 5, "bar": {"baz": 8}}})) diff --git a/Solutions/175.py b/Solutions/175.py index 503b1ff..90e91fd 100644 --- a/Solutions/175.py +++ b/Solutions/175.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given a starting state start, a list of transition probabilities for a Markov chain, and a number of steps num_steps. @@ -20,7 +20,7 @@ ('c', 'c', 0.5) ] One instance of running this Markov chain might produce {'a': 3012, 'b': 1656, 'c': 332 } -''' +""" # imporing randint from random import random @@ -30,20 +30,20 @@ class Graph: # initialization def __init__(self): self.nodes = {} - + # adding new node def add_node(self, node): self.nodes[node] = {} - + # adding the edges with the required probability def add_transition_probability(self, node1, node2, probability): - if (node1 not in self.nodes): + if node1 not in self.nodes: self.add_node(node1) - if (node2 not in self.nodes): + if node2 not in self.nodes: self.add_node(node2) - + self.nodes[node1][node2] = probability - + # getting the node being transitioned to def transition(self, node): transition = random() @@ -51,9 +51,10 @@ def transition(self, node): for key in self.nodes[node]: curr += self.nodes[node][key] - if (curr > transition): + if curr > transition: return key + # FUNCTION TO PERFORM THE OPERATION def get_transitions(start, transitions, steps): # initializing the graph @@ -65,37 +66,38 @@ def get_transitions(start, transitions, steps): for x, y, _ in transitions: nodes.add(x) nodes.add(y) - + # creating a visited frequency dictionary visited = {node: 0 for node in nodes} - + # creating the graph for transition in transitions: node1, node2, probability = transition graph.add_transition_probability(node1, node2, probability) - + # initializing the traversal node = graph.transition(start) visited[node] += 1 # traversing and storing the details - for _ in range(steps-1): + for _ in range(steps - 1): node = graph.transition(node) visited[node] += 1 - + # returning the visited frequency return visited + # DRIVER CODE transitions = [ - ('a', 'a', 0.9), - ('a', 'b', 0.075), - ('a', 'c', 0.025), - ('b', 'a', 0.15), - ('b', 'b', 0.8), - ('b', 'c', 0.05), - ('c', 'a', 0.25), - ('c', 'b', 0.25), - ('c', 'c', 0.5) + ("a", "a", 0.9), + ("a", "b", 0.075), + ("a", "c", 0.025), + ("b", "a", 0.15), + ("b", "b", 0.8), + ("b", "c", 0.05), + ("c", "a", 0.25), + ("c", "b", 0.25), + ("c", "c", 0.5), ] -print(get_transitions('a', transitions, 5000)) \ No newline at end of file +print(get_transitions("a", transitions, 5000)) diff --git a/Solutions/176.py b/Solutions/176.py index 3d9337e..ca961d5 100644 --- a/Solutions/176.py +++ b/Solutions/176.py @@ -1,4 +1,4 @@ -''' +""" Problem: Determine whether there exists a one-to-one character mapping from one string s1 to another s2. @@ -12,7 +12,7 @@ s1 = 'foo' s2 = 'bar' Output = false (since the 'o' cannot map to two characters) -''' +""" # FUNCTION TO PERFORM THE OPERATION def check(s1, s2): @@ -23,26 +23,27 @@ def check(s1, s2): # creating a dictionary d = {} - # checking if each character of s1 maps to a unique character of s2 + # checking if each character of s1 maps to a unique character of s2 # (part of the condition for one-to-one map) for i in range(l1): - if (s1[i] in d and d[s1[i]] != s2[i]): + if s1[i] in d and d[s1[i]] != s2[i]: return False d[s1[i]] = s2[i] - + # creating a dictionary d = {} - # checking if each character of s2 maps to a unique character of s1 + # checking if each character of s2 maps to a unique character of s1 # (part of the condition for one-to-one map) for i in range(l2): - if (s2[i] in d and d[s2[i]] != s1[i]): + if s2[i] in d and d[s2[i]] != s1[i]: return False d[s2[i]] = s1[i] - + # returning True if both the conditions are satisfied return True + # DRIVER CODE -print(check('abc', 'bcd')) -print(check('abc', 'foo')) \ No newline at end of file +print(check("abc", "bcd")) +print(check("abc", "foo")) diff --git a/Solutions/177.py b/Solutions/177.py index 4e49eb5..bf54b8e 100644 --- a/Solutions/177.py +++ b/Solutions/177.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a linked list and a positive integer k, rotate the list to the right by k places. @@ -12,7 +12,7 @@ Linked list = 1 -> 2 -> 3 -> 4 -> 5 k = 3 Output = 3 -> 4 -> 5 -> 1 -> 2 -''' +""" # importing the necessary classes from DataStructures.LinkedList import Linked_list, Node @@ -30,8 +30,9 @@ def rot_right(self, k=0): self.rear.next = temp self.rear = self.rear.next + # binding the function to the linked list class -setattr(Linked_list, 'rot_right', rot_right) +setattr(Linked_list, "rot_right", rot_right) # DRIVER CODE LL = Linked_list() @@ -45,4 +46,4 @@ def rot_right(self, k=0): LL.rot_right(3) -print(LL) \ No newline at end of file +print(LL) diff --git a/Solutions/178.py b/Solutions/178.py index 78f8755..5a7dc6b 100644 --- a/Solutions/178.py +++ b/Solutions/178.py @@ -1,4 +1,4 @@ -''' +""" Problem: Alice wants to join her school's Probability Student Club. @@ -11,7 +11,7 @@ Which of the two games should Alice elect to play? Does it even matter? Write a program to simulate the two games and calculate their expected value. -''' +""" # importing randint to simulate dice roll and sleep for displaying the simulation from random import randint @@ -21,6 +21,7 @@ def dice_roll(): return randint(1, 6) + # FUNCTION TO PERFORM THE OPERATION def game(stopping_cond, display=False): # temp1 and temp2 stores the last 2 throws @@ -30,7 +31,7 @@ def game(stopping_cond, display=False): counter = 0 # simulation the game - while (temp1 != stopping_cond[1] or temp2 != stopping_cond[0]): + while temp1 != stopping_cond[1] or temp2 != stopping_cond[0]: # rolling the dice and updating temp1 and temp2 val = dice_roll() temp2 = temp1 @@ -38,19 +39,19 @@ def game(stopping_cond, display=False): counter += 1 # displaying the simulation if the user whished to see it - if (display): + if display: sleep(0.1) print(f"On {counter}th throw, value: {val}") - # displaying the simulation if the user whished to see it - if (display): + if display: sleep(0.1) print(f"Total Value: {counter}\n") # returning the number of rolls return counter + # DRIVER CODE # simulation @@ -68,4 +69,4 @@ def game(stopping_cond, display=False): g2 += game((5, 5)) print("Expectation of Game 1: {:.1f}".format(g1 / 10000)) -print("Expectation of Game 2: {:.1f}".format(g2 / 10000)) \ No newline at end of file +print("Expectation of Game 2: {:.1f}".format(g2 / 10000)) diff --git a/Solutions/179.py b/Solutions/179.py index 620acbc..f8817ed 100644 --- a/Solutions/179.py +++ b/Solutions/179.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given the sequence of keys visited by a postorder traversal of a binary search tree, reconstruct the tree. @@ -12,7 +12,7 @@ 3 7 / \ \ 2 4 8 -''' +""" # importing the required classes from the Datastructures module from DataStructures.Tree import Binary_Search_Tree, Node @@ -23,19 +23,21 @@ def construct(tree, postorder): for val in postorder: tree.add(val) + # FUNCTION TO PERFORM THE OPERATION def bst_from_postorder(postorder): # creating the bst tree = Binary_Search_Tree() # if there are elements in the postorder traversal - # the root is added and the construct function is called to create the rest of the tree + # the root is added and the construct function is called to create the rest of the tree # (reversed postorder array is passed excluding the root element) - if (postorder): + if postorder: tree.add(postorder[-1]) construct(tree, postorder[-2::-1]) return tree + # DRIVER CODE -print(bst_from_postorder([2, 4, 3, 8, 7, 5])) \ No newline at end of file +print(bst_from_postorder([2, 4, 3, 8, 7, 5])) diff --git a/Solutions/18.py b/Solutions/18.py index b65b3ff..8e652de 100644 --- a/Solutions/18.py +++ b/Solutions/18.py @@ -1,9 +1,9 @@ -''' +""" Problem: Given an array of integers and a number k, where 1 <= k <= length of the array, compute the maximum values of each subarray of length k. [10, 5, 2, 7, 8, 7], 3 => [10, 7, 8, 8] -''' +""" # FUNCTION TO PERFORM THE OPERATION def calc_max_per_k(arr, k): @@ -12,28 +12,29 @@ def calc_max_per_k(arr, k): max_curr = max(arr[:k]) # looping over from k'th pos to the end of the array - for i in range(length-k+1): + for i in range(length - k + 1): # setting the start and the end of the window frame start = i end = i + k - 1 - + # temporary cariable to store the current maximum temp = max_curr - + # if the element at the start is the maximum, current max is recalculated - if (arr[start] == max_curr): - max_curr = max(arr[start+1:end+2]) - + if arr[start] == max_curr: + max_curr = max(arr[start + 1 : end + 2]) + # if the next element to be considered in the window is larger, current max is set to that value - elif (end < (length-1) and max_curr < arr[end+1]): - max_curr = arr[end+1] - + elif end < (length - 1) and max_curr < arr[end + 1]: + max_curr = arr[end + 1] + # start of the moving window is set to the current max for the iteration arr[start] = temp # returning the values till start - return arr[:start+1] + return arr[: start + 1] + # DRIVER CODE print(calc_max_per_k([10, 5, 2, 7, 8, 7], 3)) -print(calc_max_per_k([1, 91, 17, 46, 45, 36, 9], 3)) \ No newline at end of file +print(calc_max_per_k([1, 91, 17, 46, 45, 36, 9], 3)) diff --git a/Solutions/180.py b/Solutions/180.py index c414bf7..0a4b4d3 100644 --- a/Solutions/180.py +++ b/Solutions/180.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a stack of N elements, interleave the first half of the stack with the second half reversed using only one other queue. @@ -13,7 +13,7 @@ Input = [1, 2, 3, 4, 5] Output = [1, 5, 2, 4, 3] -''' +""" # importing necessary classes from Datastructures module from DataStructures.Stack import Stack @@ -23,17 +23,18 @@ def interleave(stack): # creating the queue queue = Queue() - + # interleaving the elements for i in range(1, len(stack)): for _ in range(i, len(stack)): queue.enqueue(stack.pop()) for _ in range(len(queue)): stack.push(queue.dequeue()) - + # returning the stack return stack + # DRIVER CODE stack = Stack() @@ -60,4 +61,4 @@ def interleave(stack): stack = interleave(stack) -print(stack) \ No newline at end of file +print(stack) diff --git a/Solutions/181.py b/Solutions/181.py index 88a4bb2..569f27d 100644 --- a/Solutions/181.py +++ b/Solutions/181.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string, split it into as few strings as possible such that each string is a palindrome. @@ -10,30 +10,31 @@ Input = "abc" Output = ["a", "b", "c"] -''' +""" # function to check if a string is palindrome def is_palindrome(string): - return (string and string == string[::-1]) + return string and string == string[::-1] + # helper function to perform the computations def split_into_strings_helper(string, current, previous): # base cases for recursion - # the entire string has been partitioned into palindromes + # the entire string has been partitioned into palindromes # (previous contains the last palindrome) - if (not string and not current): + if not string and not current: return previous - # the string has been exhausted, but could not obtain a palindrome using the last characters + # the string has been exhausted, but could not obtain a palindrome using the last characters # (each character in the string is used as a palindrome) - elif (not string): + elif not string: return previous + list(current) # generating temp temp = current + string[0] # checking if temp is a palindrome - if (is_palindrome(temp)): + if is_palindrome(temp): # adding temp to the list of palindromes temp_arr_1 = split_into_strings_helper(string[1:], "", previous + [temp]) # checking if a larger palindrome can be obtained @@ -41,17 +42,19 @@ def split_into_strings_helper(string, current, previous): # returning the shorter list return min(temp_arr_1, temp_arr_2, key=lambda List: len(List)) - + # if the temp is not a palindrome, the search for a palindrome continues else: return split_into_strings_helper(string[1:], temp, previous) + # FUNCTION TO PERFORM THE OPERATION def split_into_strings(string): # calling the helper function return split_into_strings_helper(string, "", []) + # DRIVER CODE print(split_into_strings("racecarannakayak")) print(split_into_strings("abc")) -print(split_into_strings("abbbc")) \ No newline at end of file +print(split_into_strings("abbbc")) diff --git a/Solutions/182.py b/Solutions/182.py index 9518f1b..a527794 100644 --- a/Solutions/182.py +++ b/Solutions/182.py @@ -1,11 +1,11 @@ -''' +""" Problem: A graph is minimally-connected if it is connected and there is no edge that can be removed while still leaving the graph connected. For example, any binary tree is minimally-connected. Given an undirected graph, check if the graph is minimally-connected. You can choose to represent the graph as either an adjacency matrix or adjacency list. -''' +""" # importing deepcopy to generate a deep copy of a dictionary from copy import deepcopy @@ -18,34 +18,35 @@ def is_minimally_connected(self): # creating a copy for the graph graph_copy = Graph_Undirected_Unweighted() graph_copy.connections = deepcopy(self.connections) - - # getting a random node to start from + + # getting a random node to start from # (the graph is undirected, so random selection is not a problem) for node in self.connections: start = node break - # running bfs and checking if a node is visited more than once + # running bfs and checking if a node is visited more than once # (redundant edges present => not a minimally connected graph) visited = set([start]) queue = [start] - while (queue): + while queue: node = queue.pop(0) for child_node in graph_copy.connections[node]: graph_copy.connections[child_node].remove(node) queue.append(child_node) - if (child_node in visited): + if child_node in visited: return False else: visited.add(child_node) - + return True + # adding the function to the graph class -setattr(Graph_Undirected_Unweighted, 'is_minimally_connected', is_minimally_connected) +setattr(Graph_Undirected_Unweighted, "is_minimally_connected", is_minimally_connected) # DRIVER CODE graph = Graph_Undirected_Unweighted() @@ -60,4 +61,4 @@ def is_minimally_connected(self): graph.add_edge(1, 4) print(graph) -print(graph.is_minimally_connected()) \ No newline at end of file +print(graph.is_minimally_connected()) diff --git a/Solutions/184.py b/Solutions/184.py index adb140f..ac0316b 100644 --- a/Solutions/184.py +++ b/Solutions/184.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given n numbers, find the greatest common denominator between them. @@ -7,7 +7,7 @@ Input = [42, 56, 14] Output = 14 -''' +""" # importingg gcd function from math module from math import gcd as gcd_of_2 @@ -15,20 +15,21 @@ # FUNCTION TO PERFORM THE OPERATION def gcd(nums): # if the array is empty, None is returned - if (not nums): + if not nums: return None - + # initializing the result result = nums[0] # finding the gcd of all the numbers for num in nums[1:]: result = gcd_of_2(result, num) - + # returning the result return result + # DRIVER CODE print(gcd([42, 56, 14])) print(gcd([3, 5])) -print(gcd([9, 15])) \ No newline at end of file +print(gcd([9, 15])) diff --git a/Solutions/185.py b/Solutions/185.py index b34fc1a..054c392 100644 --- a/Solutions/185.py +++ b/Solutions/185.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given two rectangles on a 2D graph, return the area of their intersection. If the rectangles don't intersect, return 0. @@ -14,49 +14,44 @@ "dimensions": (4, 3) # width, height } Output = 6 -''' +""" # FUNCTION TO PERFORM THE OPERATION def intersection(rectangle1, rectangle2): # segregating the rectangles by x-axis - if (rectangle1["top_left"][0] < rectangle2["top_left"][0]): + if rectangle1["top_left"][0] < rectangle2["top_left"][0]: left = rectangle1 right = rectangle2 else: left = rectangle2 right = rectangle1 - + # segregating the rectangles by y-axis - if (rectangle1["top_left"][1] > rectangle2["top_left"][1]): + if rectangle1["top_left"][1] > rectangle2["top_left"][1]: top = rectangle1 bottom = rectangle2 else: top = rectangle2 bottom = rectangle1 - + # getting the length of overlap on x-axis - if ((left["top_left"][0] + left["dimensions"][0]) < right["top_left"][0]): + if (left["top_left"][0] + left["dimensions"][0]) < right["top_left"][0]: span_x = 0 else: span_x = (left["top_left"][0] + left["dimensions"][0]) - right["top_left"][0] # getting the length of overlap on y-axis - if ((top["top_left"][1] - top["dimensions"][1]) > bottom["top_left"][1]): + if (top["top_left"][1] - top["dimensions"][1]) > bottom["top_left"][1]: span_y = 0 else: span_y = bottom["top_left"][1] - (top["top_left"][1] - top["dimensions"][1]) - + # returning the overlapped area - return (span_x * span_y) + return span_x * span_y + # DRIVER CODE -rectangle1 = { - "top_left": (1, 4), - "dimensions": (3, 3) # width, height -} -rectangle2 = { - "top_left": (0, 5), - "dimensions": (4, 3) # width, height -} +rectangle1 = {"top_left": (1, 4), "dimensions": (3, 3)} # width, height +rectangle2 = {"top_left": (0, 5), "dimensions": (4, 3)} # width, height -print(intersection(rectangle1, rectangle2)) \ No newline at end of file +print(intersection(rectangle1, rectangle2)) diff --git a/Solutions/186.py b/Solutions/186.py index 6a465d9..b3a6cb9 100644 --- a/Solutions/186.py +++ b/Solutions/186.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an array of positive integers. @@ -8,32 +8,33 @@ Input = [5, 10, 15, 20, 25] Output = {10, 25}, {5, 15, 20} (which has a difference of 5, which is the smallest possible difference) -''' +""" # FUNCTION TO PERFORM THE OPERATION def smallest_difference_sets(arr, set1=[], set2=[]): # if all the elements of the array has been considered, the sets are returned - if (not arr): + if not arr: return set1, set2 - + # the last element of the array is selected temp = arr.pop() - + # generating the 2 sets for each permutation (adding the last element to set1 or set2) - temp1_1, temp2_1 = smallest_difference_sets(list(arr), set1+[temp], list(set2)) - temp1_2, temp2_2 = smallest_difference_sets(list(arr), list(set1), set2+[temp]) - + temp1_1, temp2_1 = smallest_difference_sets(list(arr), set1 + [temp], list(set2)) + temp1_2, temp2_2 = smallest_difference_sets(list(arr), list(set1), set2 + [temp]) + # getting the difference in each case diff1 = abs(sum(temp1_1) - sum(temp2_1)) diff2 = abs(sum(temp1_2) - sum(temp2_2)) # returning the sets where the difference is minimum - if (diff1 < diff2): + if diff1 < diff2: return temp1_1, temp2_1 else: return temp1_2, temp2_2 + # DRIVER CODE print(smallest_difference_sets([5, 10, 15, 20, 25], [], [])) print(smallest_difference_sets([5, 10, 15, 20], [], [])) -print(smallest_difference_sets([500, 10, 15, 20, 25], [], [])) \ No newline at end of file +print(smallest_difference_sets([500, 10, 15, 20, 25], [], [])) diff --git a/Solutions/187.py b/Solutions/187.py index fdfe37d..f59149c 100644 --- a/Solutions/187.py +++ b/Solutions/187.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given given a list of rectangles represented by min and max x- and y-coordinates. @@ -19,40 +19,41 @@ "dimensions": (4, 3) }] Output = true (as the first and third rectangle overlap each other) -''' +""" # helper function to calculate the area under 2 rectangles (Used in problem 185) def intersection(rect1, rect2): # segregating the rectangles by x-axis - if (rect1["top_left"][0] < rect2["top_left"][0]): + if rect1["top_left"][0] < rect2["top_left"][0]: left = rect1 right = rect2 else: left = rect2 right = rect1 - + # segregating the rectangles by y-axis - if (rect1["top_left"][1] > rect2["top_left"][1]): + if rect1["top_left"][1] > rect2["top_left"][1]: top = rect1 bottom = rect2 else: top = rect2 bottom = rect1 - + # getting the length of overlap on x-axis - if ((left["top_left"][0] + left["dimensions"][0]) < right["top_left"][0]): + if (left["top_left"][0] + left["dimensions"][0]) < right["top_left"][0]: return 0 else: span_x = (left["top_left"][0] + left["dimensions"][0]) - right["top_left"][0] # getting the length of overlap on y-axis - if ((top["top_left"][1] - top["dimensions"][1]) > bottom["top_left"][1]): + if (top["top_left"][1] - top["dimensions"][1]) > bottom["top_left"][1]: return 0 else: span_y = bottom["top_left"][1] - (top["top_left"][1] - top["dimensions"][1]) - + # returning the overlapped area - return (span_x * span_y) + return span_x * span_y + # FUNCTION TO PERFORM THE OPERATION def check_rectangles_intersection(rectangles): @@ -60,29 +61,23 @@ def check_rectangles_intersection(rectangles): length = len(rectangles) # checking for intersection for each pair of rectangles - for i in range(length-1): - for j in range(i+1, length): - if (intersection(rectangles[i], rectangles[j]) != 0): + for i in range(length - 1): + for j in range(i + 1, length): + if intersection(rectangles[i], rectangles[j]) != 0: return True - + return False + # DRIVER CODE -rectangles = [{ - "top_left": (1, 4), - "dimensions": (3, 3) -}, -{ - "top_left": (-1, 3), - "dimensions": (2, 1) -}, -{ - "top_left": (0, 5), - "dimensions": (4, 3) -}] +rectangles = [ + {"top_left": (1, 4), "dimensions": (3, 3)}, + {"top_left": (-1, 3), "dimensions": (2, 1)}, + {"top_left": (0, 5), "dimensions": (4, 3)}, +] print(check_rectangles_intersection(rectangles)) rectangles.pop(2) -print(check_rectangles_intersection(rectangles)) \ No newline at end of file +print(check_rectangles_intersection(rectangles)) diff --git a/Solutions/188.py b/Solutions/188.py index f42ece1..baca8af 100644 --- a/Solutions/188.py +++ b/Solutions/188.py @@ -1,4 +1,4 @@ -''' +""" Problem: What will this code print out? @@ -18,10 +18,11 @@ def print_i(): f() How can we make it print out what we apparently want? -''' +""" # The code will print 3 thrice (in 3 lines) as i is passed by reference + def make_functions(): flist = [] @@ -30,6 +31,7 @@ def make_functions(): # this program shows the minimum necessary changes required to print 1 to 3 def print_i(i): print(i) + flist.append((print_i, i)) return flist @@ -37,4 +39,4 @@ def print_i(i): functions = make_functions() for f, i in functions: - f(i) \ No newline at end of file + f(i) diff --git a/Solutions/189.py b/Solutions/189.py index ebe939f..35dd02b 100644 --- a/Solutions/189.py +++ b/Solutions/189.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of elements, return the length of the longest subarray where all its elements are distinct. @@ -7,12 +7,12 @@ Input = [5, 1, 3, 5, 2, 3, 4, 1] Output = 5 (as the longest subarray of distinct elements is [5, 2, 3, 4, 1]) -''' +""" # FUNCTION TO PERFORM THE OPERATION def max_unique_subarr(arr): # check for empty array - if (not arr): + if not arr: return 0 # declaring the required variables @@ -25,32 +25,32 @@ def max_unique_subarr(arr): # iterating through the array for i in range(length): # if the element is not present in the moving window, its added to cache - if (arr[i] not in cache): + if arr[i] not in cache: cache.add(arr[i]) curr_len += 1 else: # updating max_len if curr_len is larger - if (max_len < curr_len): + if max_len < curr_len: max_len = curr_len - + # if the element is present in the moving window, the elements before the 1st occurence in the window are removed for j in range(pos, i): cache.remove(arr[j]) curr_len -= 1 # when the 1st occurance is found, the required updates are done and the control breaks out of the loop - if (arr[j] == arr[i]): + if arr[j] == arr[i]: pos = j cache.add(arr[j]) curr_len += 1 break - - + # updating max_len after exiting the loop - if (max_len < curr_len): + if max_len < curr_len: max_len = curr_len - + return max_len + # DRIVER CODE -print(max_unique_subarr([5, 1, 3, 5, 2, 3, 4, 1, 5])) \ No newline at end of file +print(max_unique_subarr([5, 1, 3, 5, 2, 3, 4, 1, 5])) diff --git a/Solutions/19.py b/Solutions/19.py index 7779bab..884753a 100644 --- a/Solutions/19.py +++ b/Solutions/19.py @@ -1,10 +1,10 @@ -''' +""" Problem: A builder is looking to build a row of N houses that can be of K different colors. He has a goal of minimizing cost while ensuring that no two neighboring houses are of the same color. Given an N by K matrix where the nth row and kth column represents the cost to build the nth house with kth color, return the minimum cost. -''' +""" # FUNCTION TO PERFORM THE OPERATION def minimizeColorCost(arr, n, k): @@ -13,22 +13,37 @@ def minimizeColorCost(arr, n, k): # calling the helper function helper(arr, results, 0, -1, 0, "", n, k) - - return min(results) # USE 'return min(results, key=lambda x: x[0])' incase you want to return the sequence too + + return min( + results + ) # USE 'return min(results, key=lambda x: x[0])' incase you want to return the sequence too + # helper function to carry out the main operations (Uses Recursion) def helper(arr, results, curr_house, prev_color, curr_cost, curr_sequence, n, k): # Base case, the sequence has been generated - if (curr_house == n): + if curr_house == n: # adding the cost to the result array - results.append(curr_cost) # USE 'results.append((curr_cost, curr_sequence))' to add the sequence too + results.append( + curr_cost + ) # USE 'results.append((curr_cost, curr_sequence))' to add the sequence too return # Loop to generate all the possible combinations for i in range(k): # When the current color is not equal to the previous color the helper function is called to generate the sequence - if (i != prev_color): - helper(arr, results, curr_house + 1, i, arr[curr_house][i] + curr_cost, curr_sequence + str(i), n, k) + if i != prev_color: + helper( + arr, + results, + curr_house + 1, + i, + arr[curr_house][i] + curr_cost, + curr_sequence + str(i), + n, + k, + ) + # DRIVER CODE mat1 = [[1, 5, 2], [2, 3, 1], [7, 3, 5], [6, 2, 3]] @@ -37,4 +52,4 @@ def helper(arr, results, curr_house, prev_color, curr_cost, curr_sequence, n, k) k = 3 print(minimizeColorCost(mat1, n, k)) -print(minimizeColorCost(mat2, n, k)) \ No newline at end of file +print(minimizeColorCost(mat2, n, k)) diff --git a/Solutions/190.py b/Solutions/190.py index 1a77671..c267db2 100644 --- a/Solutions/190.py +++ b/Solutions/190.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a circular array, compute its maximum subarray sum in O(n) time. @@ -10,7 +10,7 @@ Input = [-4, 5, 1, 0] Output = 6 (as we choose the numbers 5 and 1) -''' +""" # helper function (max of array using Kadane's algorithm) def kadane(arr): @@ -27,9 +27,10 @@ def kadane(arr): curr_sum = max(curr_sum, 0) # updating max sum to hold the maximum max_sum = max(max_sum, curr_sum) - + return max_sum + # FUNCTION TO PERFORM THE OPERATION def max_circular_subarr(arr): # getting the length of the array @@ -51,8 +52,9 @@ def max_circular_subarr(arr): # returning the maximum of wrapped sum and kadane's result return max(max_wrap, max_kadane) + # DRIVER CODE print(max_circular_subarr([-4, 5, 1, 0])) print(max_circular_subarr([8, -1, 3, 4])) print(max_circular_subarr([-8, -1, -3, -4])) -print(max_circular_subarr([8, -1, 300, -1, 4])) \ No newline at end of file +print(max_circular_subarr([8, -1, 300, -1, 4])) diff --git a/Solutions/191.py b/Solutions/191.py index df8bdf6..d028d58 100644 --- a/Solutions/191.py +++ b/Solutions/191.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a collection of intervals, find the minimum number of intervals you need to remove to make the rest of the intervals non-overlapping. @@ -9,12 +9,12 @@ Input = (7, 9), (2, 4), (5, 8) Output = 1 (as the last interval can be removed and the first two won't overlap) -''' +""" # FUNCTION TO PERFORM THE OPERATION def num_overlap(arr): # cache to store whether a time frame falls in the input time interval - cache = [0 for _ in range(max(max(arr))+1)] + cache = [0 for _ in range(max(max(arr)) + 1)] # variable to store the overlap count overlap_count = 0 @@ -25,23 +25,24 @@ def num_overlap(arr): # flag checks for overlap flag = True - # iterating through the interval range + # iterating through the interval range # (to end-1 as 2 intervals may have the same end and start time without overlaping) for i in range(start, end): # checking if the value in the cache is 0 (no overlap) - if (cache[i] == 0): + if cache[i] == 0: cache[i] = 1 else: # if an overlap occurs, overlap count is incremented # flag is unset so that the overlap is counted once - if (flag): + if flag: overlap_count += 1 flag = False - + # returning overlap count return overlap_count + # DRIVER CODE print(num_overlap([[0, 1], [1, 2]])) print(num_overlap([(7, 9), (2, 4), (5, 8)])) -print(num_overlap([(7, 9), (2, 4), (5, 8), (1, 3)])) \ No newline at end of file +print(num_overlap([(7, 9), (2, 4), (5, 8), (1, 3)])) diff --git a/Solutions/192.py b/Solutions/192.py index b14e623..3b8eab9 100644 --- a/Solutions/192.py +++ b/Solutions/192.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an array of nonnegative integers. @@ -12,7 +12,7 @@ Input = [1, 2, 1, 0, 0] Output = False (we can't reach the end) -''' +""" # FUNCTION TO PERFORM THE OPERATION def can_reach_end(arr): @@ -22,19 +22,20 @@ def can_reach_end(arr): # creating a array to use dynamic programming dp = [False for _ in range(length)] # base case (the end is reached) - dp[length-1] = True + dp[length - 1] = True # iterating through the elements from the end - for i in range(length-2, -1, -1): + for i in range(length - 2, -1, -1): # checking for an element in the reach of current position, from which the end can be reached - for j in range(i+1, min(length, i+arr[i]+1)): + for j in range(i + 1, min(length, i + arr[i] + 1)): # if such an element is found, the array is updated and the control breaks out of the loop - if (dp[j]): + if dp[j]: dp[i] = True break - + return dp[0] + # DRIVER CODE print(can_reach_end([1, 3, 1, 2, 0, 1])) -print(can_reach_end([1, 2, 1, 0, 0])) \ No newline at end of file +print(can_reach_end([1, 2, 1, 0, 0])) diff --git a/Solutions/193.py b/Solutions/193.py index 66b298c..deb5460 100644 --- a/Solutions/193.py +++ b/Solutions/193.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a array of numbers representing the stock prices of a company in chronological order, write a function that calculates the maximum profit you could have made from buying and selling that stock. @@ -12,27 +12,28 @@ Output = 9 (Since you could buy the stock at $1, and sell at $8, and then buy it at $4 and sell it at $10. Since we did two transactions, there is a $4 fee, so we have 7 + 6 = 13 profit minus $4 of fees.) -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_max_profit(prices, fee, profit=0, current=0, can_buy=True): # if the price array is empty, the profit is returned - if (not prices): + if not prices: return profit - + # if buying is permitted, checking for holding the stock and buying at the current price - if (can_buy): + if can_buy: return max( - get_max_profit(prices[1:], fee, profit, -prices[0]-fee, False), - get_max_profit(prices[1:], fee, profit, 0, True) + get_max_profit(prices[1:], fee, profit, -prices[0] - fee, False), + get_max_profit(prices[1:], fee, profit, 0, True), ) # if selling is permitted, checking for holding the stock and selling at the current price else: return max( - get_max_profit(prices[1:], fee, profit+(current+prices[0]), 0, True), - get_max_profit(prices[1:], fee, profit, current, False) + get_max_profit(prices[1:], fee, profit + (current + prices[0]), 0, True), + get_max_profit(prices[1:], fee, profit, current, False), ) + # DRIVER CODE print(get_max_profit([1, 3, 2, 8, 4, 10], 2)) -print(get_max_profit([1, 3, 2, 1, 4, 10], 2)) \ No newline at end of file +print(get_max_profit([1, 3, 2, 1, 4, 10], 2)) diff --git a/Solutions/194.py b/Solutions/194.py index d93bc7e..307d728 100644 --- a/Solutions/194.py +++ b/Solutions/194.py @@ -1,10 +1,10 @@ -''' +""" Problem: Suppose you are given two lists of n points, one list p1, p2, ..., pn on the line y = 0 and the other list q1, q2, ..., qn on the line y = 1. Imagine a set of n line segments connecting each point pi to qi. Write an algorithm to determine how many pairs of the line segments intersect. -''' +""" # FUNCTION TO PERFORM THE OPERATION def num_intersect(arr1, arr2): @@ -19,12 +19,15 @@ def num_intersect(arr1, arr2): # checking if any other points intersect it for p2_start, p2_end in segments[:i]: - if ((p1_start < p2_start and p1_end > p2_end) or (p1_start > p2_start and p1_end < p2_end)): + if (p1_start < p2_start and p1_end > p2_end) or ( + p1_start > p2_start and p1_end < p2_end + ): count += 1 return count + # DRIVER CODE print(num_intersect([1, 2, 3, 4], [3, 2, 3, 2])) print(num_intersect([1, 4, 5], [4, 2, 3])) -print(num_intersect([1, 4, 5], [2, 3, 4])) \ No newline at end of file +print(num_intersect([1, 4, 5], [2, 3, 4])) diff --git a/Solutions/195.py b/Solutions/195.py index 1bd260b..e390ec0 100644 --- a/Solutions/195.py +++ b/Solutions/195.py @@ -1,43 +1,34 @@ -''' +""" Problem: Let M be an N by N matrix in which every row and every column is sorted. No two elements of M are equal. Given i1, j1, i2, and j2, compute the number of elements of M smaller than M[i1, j1] and larger than M[i2, j2]. -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_num_in_range(mat, i1, j1, i2, j2): # getting the numbers - num1, num2 = mat[i1][j1], mat[i2][j2] - + num1, num2 = mat[i1][j1], mat[i2][j2] + # iterating through the matrix and finding the necessary elements count = sum([len([x for x in row if (x < num1 and x > num2)]) for row in mat]) - + # returning the count return count + # DRIVER CODE mat = [ - [1, 3, 7, 10, 15, 20], - [2, 6, 9, 14, 22, 25], - [3, 8, 10, 15, 25, 30], - [10, 11, 12, 23, 30, 35], - [20, 25, 30, 35, 40, 45] + [1, 3, 7, 10, 15, 20], + [2, 6, 9, 14, 22, 25], + [3, 8, 10, 15, 25, 30], + [10, 11, 12, 23, 30, 35], + [20, 25, 30, 35, 40, 45], ] print(get_num_in_range(mat, 3, 3, 1, 1)) -matrix = [ - [1, 2, 3, 4], - [5, 8, 9, 13], - [6, 10, 12, 14], - [7, 11, 15, 16] -] +matrix = [[1, 2, 3, 4], [5, 8, 9, 13], [6, 10, 12, 14], [7, 11, 15, 16]] print(get_num_in_range(matrix, 1, 3, 3, 1)) -matrix = [ - [1, 2, 3, 4], - [5, 6, 7, 8], - [10, 11, 12, 13], - [20, 21, 22, 23] -] -print(get_num_in_range(matrix, 3, 3, 1, 0)) \ No newline at end of file +matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [10, 11, 12, 13], [20, 21, 22, 23]] +print(get_num_in_range(matrix, 3, 3, 1, 0)) diff --git a/Solutions/196.py b/Solutions/196.py index a9b621e..32447a1 100644 --- a/Solutions/196.py +++ b/Solutions/196.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given the root of a binary tree, find the most frequent subtree sum. @@ -11,28 +11,29 @@ / \ 2 -5 Output = 2 (as it occurs twice: once as the left leaf, and once as the sum of 2 + 5 - 5) -''' +""" # importing from the Datastructure module from DataStructures.Tree import Node, Binary_Tree # function to count the frequency of a value def add_to_freq_count(val, dictionary): - if (val in dictionary): + if val in dictionary: dictionary[val] += 1 else: dictionary[val] = 1 return dictionary - + + # helper function to get the freqency def get_frequent_subtree_sum_helper(self, sum_freq={}): # checking if the node is a leaf node - if (self.left == None and self.right == None): + if self.left == None and self.right == None: # adding the leaf value to the frequency and returning in the format (freq, current_sum) return add_to_freq_count(self.val, sum_freq), self.val # checking if the node has a left child but not the right child - elif (self.left != None and self.right == None): + elif self.left != None and self.right == None: # getting the left frequency and the left sum sum_freq, current = self.left.get_frequent_subtree_sum_helper(sum_freq) # getting the current sum @@ -41,7 +42,7 @@ def get_frequent_subtree_sum_helper(self, sum_freq={}): return add_to_freq_count(current, sum_freq), current # checking if the node has a right child but not the left child - elif (self.left == None and self.right != None): + elif self.left == None and self.right != None: # getting the left frequency and the left sum sum_freq, current = self.right.get_frequent_subtree_sum_helper(sum_freq) # getting the current sum @@ -50,7 +51,7 @@ def get_frequent_subtree_sum_helper(self, sum_freq={}): return add_to_freq_count(current, sum_freq), current # if the node has both children - elif (self.left != None and self.right != None): + elif self.left != None and self.right != None: # getting the frequency and the sum for left and right sub-trees sum_freq, current_left = self.left.get_frequent_subtree_sum_helper(sum_freq) sum_freq, current_right = self.right.get_frequent_subtree_sum_helper(sum_freq) @@ -60,6 +61,7 @@ def get_frequent_subtree_sum_helper(self, sum_freq={}): # adding the value to the frequency and returning in the format (freq, current_sum) return add_to_freq_count(current, sum_freq), current + # FUNCTION TO PERFORM THE OPERATION def get_frequent_subtree_sum(self): # getting the frequency dictionary @@ -70,15 +72,16 @@ def get_frequent_subtree_sum(self): # finding the most frequent value for key, val in freq.items(): - if (val > frequency): + if val > frequency: frequency = val res = key # returning the most frequent value return res + # adding the functions to the necessary classes -setattr(Node, 'get_frequent_subtree_sum_helper', get_frequent_subtree_sum_helper) -setattr(Binary_Tree, 'get_frequent_subtree_sum', get_frequent_subtree_sum) +setattr(Node, "get_frequent_subtree_sum_helper", get_frequent_subtree_sum_helper) +setattr(Binary_Tree, "get_frequent_subtree_sum", get_frequent_subtree_sum) # DRIVER CODE tree = Binary_Tree() @@ -89,4 +92,4 @@ def get_frequent_subtree_sum(self): print(tree) -print(tree.get_frequent_subtree_sum()) \ No newline at end of file +print(tree.get_frequent_subtree_sum()) diff --git a/Solutions/197.py b/Solutions/197.py index 1f644c2..44970c6 100644 --- a/Solutions/197.py +++ b/Solutions/197.py @@ -1,8 +1,8 @@ -''' +""" Problem: Given an array and a number `k` that's smaller than the length of the array, rotate the array to the right `k` elements in-place. -''' +""" # FUNCTION TO PERFORM THE OPERATION def rotate_right(arr, k): @@ -10,20 +10,21 @@ def rotate_right(arr, k): length = len(arr) # checking if the rotation has to be performed - if (k != 0): + if k != 0: # storing the part to be shifted to the front in cache cache = arr[-k:] # shifting the necessary front part to the end for i in range(length - k - 1, -1, -1): - arr[k+i] = arr[i] - + arr[k + i] = arr[i] + # adding the end (in cache) to the front arr[:k] = cache - + return arr + # DRIVER CODE print(rotate_right([(i + 1) for i in range(5)], 3)) print(rotate_right([(i + 1) for i in range(5)], 2)) -print(rotate_right([(i + 1) for i in range(5)], 1)) \ No newline at end of file +print(rotate_right([(i + 1) for i in range(5)], 1)) diff --git a/Solutions/198.py b/Solutions/198.py index 2517e16..ce1697b 100644 --- a/Solutions/198.py +++ b/Solutions/198.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a set of distinct positive integers, find the largest subset such that every pair of elements in the subset (i, j) satisfies either i % j = 0 or j % i = 0. @@ -10,24 +10,26 @@ Input = [1, 3, 6, 24] Output = [1, 3, 6, 24] -''' +""" # helper function to perform the computation def get_largest_subset_helper(arr, prev_num=1, curr_ind=0, prev_subset=[]): # if the end of the array has been reached, the previous subsets are returned (base for recursion) - if (curr_ind == len(arr)): + if curr_ind == len(arr): return prev_subset # getting the current element curr_elem = arr[curr_ind] # calling the helper function recursively - res = get_largest_subset_helper(arr, prev_num, curr_ind+1, prev_subset) + res = get_largest_subset_helper(arr, prev_num, curr_ind + 1, prev_subset) # checking if the element is divisible by the last element (since it would contain all other smaller factors too) - if (curr_elem % prev_num == 0): + if curr_elem % prev_num == 0: # generating the alternate result (with the element added) - alternate_res = get_largest_subset_helper(arr, curr_elem, curr_ind+1, prev_subset+[curr_elem]) + alternate_res = get_largest_subset_helper( + arr, curr_elem, curr_ind + 1, prev_subset + [curr_elem] + ) # returning the longer result return max(alternate_res, res, key=lambda result: len(result)) @@ -35,6 +37,7 @@ def get_largest_subset_helper(arr, prev_num=1, curr_ind=0, prev_subset=[]): # returning the result in case its not divisible return res + # FUNCTION TO PERFORM THE OPERATION def get_largest_subset(arr): # sorting the array @@ -42,6 +45,7 @@ def get_largest_subset(arr): # calling the helper function on the array return get_largest_subset_helper(arr, prev_subset=[]) + # DRIVER CODE print(get_largest_subset([])) print(get_largest_subset([2])) @@ -49,4 +53,4 @@ def get_largest_subset(arr): print(get_largest_subset([3, 5, 10, 20, 21])) print(get_largest_subset([1, 3, 6, 24])) print(get_largest_subset([3, 9, 15, 30])) -print(get_largest_subset([2, 3, 9, 15, 30])) \ No newline at end of file +print(get_largest_subset([2, 3, 9, 15, 30])) diff --git a/Solutions/199.py b/Solutions/199.py index 6143c39..764574a 100644 --- a/Solutions/199.py +++ b/Solutions/199.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string of parentheses, find the balanced string that can be produced from it using the minimum number of insertions and deletions. @@ -11,36 +11,46 @@ Input = "))()(" Output = "()()()()" -''' +""" # helper function for the computation def get_min_changes_helper(string, modifications, stack, current): # base case for recursion (both the string and the stack is exhausted) - if (not string and not stack): + if not string and not stack: return modifications, current # base case for recursion (the string is exhausted and the stack still has elements) - elif (not string): + elif not string: additions = len(stack) - return modifications+additions, current+(")"*additions) + return modifications + additions, current + (")" * additions) # if the current element is "(" - if (string[0] == "("): + if string[0] == "(": # getting the modifications and the strings for adding the element to the stack or modifying it - modifications1, string1 = get_min_changes_helper(string[1:], modifications, stack+["("], current+"(") - modifications2, string2 = get_min_changes_helper(string[1:], modifications+1, stack, current) + modifications1, string1 = get_min_changes_helper( + string[1:], modifications, stack + ["("], current + "(" + ) + modifications2, string2 = get_min_changes_helper( + string[1:], modifications + 1, stack, current + ) # returning the required element - return min([(modifications1, string1), (modifications2, string2)], key=lambda tup: tup[0]) - + return min( + [(modifications1, string1), (modifications2, string2)], + key=lambda tup: tup[0], + ) + # if the current element is ")" else: # if the stack holds elements, 1 "(" is poped and getting the modifications and the string - if (stack): + if stack: stack.pop() - return get_min_changes_helper(string[1:], modifications, stack, current+")") + return get_min_changes_helper( + string[1:], modifications, stack, current + ")" + ) # else modifications is incremented and getting the modifications and the string else: - return get_min_changes_helper(string[1:], modifications+1, stack, current) + return get_min_changes_helper(string[1:], modifications + 1, stack, current) + # FUNCTION TO PERFORM THE OPERATION def get_min_changes(string): @@ -48,10 +58,11 @@ def get_min_changes(string): _, res = get_min_changes_helper(string, 0, [], "") return res + # DRIVER CODE print(get_min_changes("(()")) print(get_min_changes("))()(")) print(get_min_changes("()(()")) print(get_min_changes("()(()))")) print(get_min_changes(")(())")) -print(get_min_changes("())(")) \ No newline at end of file +print(get_min_changes("())(")) diff --git a/Solutions/20.py b/Solutions/20.py index 00563cb..1939e9b 100644 --- a/Solutions/20.py +++ b/Solutions/20.py @@ -1,8 +1,8 @@ -''' +""" Problem: Given 2 Linked List, find out whether they share a common node. If there is a common node, find the common node. -''' +""" # Local Import from the datastructure module @@ -12,71 +12,73 @@ def common_node(LL1, LL2): # Traversing to the end of the 1st Linked List pos1 = LL1.head - while (pos1.next != None): + while pos1.next != None: pos1 = pos1.next - + # Traversing to the end of the 2nd Linked List pos2 = LL2.head - while (pos2.next != None): + while pos2.next != None: pos2 = pos2.next - + # If the location of the last nodes of the lists are same, then they must share a common node # NOTE: 'is' is used in place of '==' to check the location and not the object (as if the values are same, '==' will return True even when the nodes are different) # WORKING METHOD: if 2 Linked Lists share a node, the structure becomes like "Y", so the end node must be same - if (pos1 is pos2): + if pos1 is pos2: return True else: return False + # FUNCTION TO PERFORM THE OPERATION (finds common node) def common_node_pos(LL1, LL2): - if (common_node(LL1, LL2)): + if common_node(LL1, LL2): # Getting the length of the Linked Lists len1 = len(LL1) len2 = len(LL2) - + # Pointers to hold the postions pos1 = LL1.head pos2 = LL2.head - if (len1 < len2): + if len1 < len2: # If 2nd list is longer, traversing to the required location (len2 - len1 as their end are same) pos = len2 - len1 for i in range(pos): pos2 = pos2.next - + # Checking whether each node is same (returns the common node), else moving to the next node for i in range(len1): - if (pos1 is pos2): + if pos1 is pos2: return pos1 pos1 = pos1.next pos2 = pos2.next - - elif (len1 == len2): + + elif len1 == len2: # Checking whether each node is same (returns the common node), else moving to the next node for i in range(len1): - if (pos1 is pos2): + if pos1 is pos2: return pos1 pos1 = pos1.next pos2 = pos2.next - + else: # If 1st list is longer, traversing to the required location (len1 - len2 as their end are same) pos = len1 - len2 for i in range(pos): pos1 = pos1.next - + # Checking whether each node is same (returns the common node), else moving to the next node for i in range(len2): - if (pos1 is pos2): + if pos1 is pos2: return pos1 pos1 = pos1.next pos2 = pos2.next - + else: return None + # DRIVER CODE (LL3 shares the last 2 nodes of LL1) LL1 = Linked_list() LL1.add(5) @@ -101,4 +103,4 @@ def common_node_pos(LL1, LL2): print("Linked List 3:", LL3) print(common_node_pos(LL1, LL2)) -print(common_node_pos(LL1, LL3)) \ No newline at end of file +print(common_node_pos(LL1, LL3)) diff --git a/Solutions/200.py b/Solutions/200.py index afb0bf5..7704e64 100644 --- a/Solutions/200.py +++ b/Solutions/200.py @@ -1,4 +1,4 @@ -''' +""" Problem: Let X be a set of n intervals on the real line. @@ -9,7 +9,7 @@ Input = [(1, 4), (4, 5), (7, 9), (9, 12)] Output = [4, 9] -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_stabs(list_of_intervals): @@ -18,5 +18,6 @@ def get_stabs(list_of_intervals): # returning the minimum value of end (start of stab) and the maximum value for start (end of stab) return min(end), max(start) + # DRIVER CODE -print(get_stabs([(1, 4), (4, 5), (7, 9), (9, 12)])) \ No newline at end of file +print(get_stabs([(1, 4), (4, 5), (7, 9), (9, 12)])) diff --git a/Solutions/201.py b/Solutions/201.py index 7e09829..d14cd41 100644 --- a/Solutions/201.py +++ b/Solutions/201.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an array of arrays of integers, where each array corresponds to a row in a triangle of numbers. @@ -14,7 +14,7 @@ 2 3 1 5 1) Output = [1 -> 3 -> 5] -''' +""" # FUNCTION TO PERFORM THE OPERATION def calc_path(triangle): @@ -22,9 +22,9 @@ def calc_path(triangle): rows = len(triangle) # few checks - if (rows == 0): + if rows == 0: return [] - elif (rows == 1): + elif rows == 1: return triangle[0] # traingle copy used for dynamic programming @@ -32,21 +32,26 @@ def calc_path(triangle): # generating the 2nd last row for i in range(len(dp[-2])): - dp[-2][i] = (max(dp[-1][i], dp[-1][i+1]) + dp[-2][i]), [max(dp[-1][i], dp[-1][i+1]), dp[-2][i]] + dp[-2][i] = ( + (max(dp[-1][i], dp[-1][i + 1]) + dp[-2][i]), + [max(dp[-1][i], dp[-1][i + 1]), dp[-2][i]], + ) # using dynamic programming to get the maximum weight (data is generated from the 3rd row from base to the peak) - for i in range(rows-3, -1, -1): - for j in range(i+1): + for i in range(rows - 3, -1, -1): + for j in range(i + 1): # getting the maximum weight path from the current position # elements stored as (weight, path) dp[i][j] = ( - (max(dp[i+1][j][0], dp[i+1][j+1][0]) + dp[i][j]), - max((dp[i+1][j], dp[i+1][j+1]), key=lambda elem: elem[0])[1] + [dp[i][j]] - ) - + (max(dp[i + 1][j][0], dp[i + 1][j + 1][0]) + dp[i][j]), + max((dp[i + 1][j], dp[i + 1][j + 1]), key=lambda elem: elem[0])[1] + + [dp[i][j]], + ) + # getting the path return dp[0][0][1][::-1] + # DRIVER CODE print(calc_path([[1], [2, 3], [1, 5, 1]])) -print(calc_path([[1], [2, 3], [7, 5, 1]])) \ No newline at end of file +print(calc_path([[1], [2, 3], [7, 5, 1]])) diff --git a/Solutions/202.py b/Solutions/202.py index d5d3713..166104e 100644 --- a/Solutions/202.py +++ b/Solutions/202.py @@ -1,4 +1,4 @@ -''' +""" Problem: Write a program that checks whether an integer is a palindrome. Do not convert the integer into a string. @@ -13,45 +13,46 @@ Input = 678 Output = False -''' +""" # FUNCTION TO PERFORM THE OPERATION def pal_check(num): # dec_places stores the number of decimal places in the number dec_place = 0 - + # getting the number of decimal places temp = num - while (temp >= 10): + while temp >= 10: dec_place += 1 temp = temp // 10 # if the number of digits is odd, the middle number is excluded from comparison - if (dec_place % 2 == 0): + if dec_place % 2 == 0: # checking if the number is a palindrome - for i in range((dec_place)//2): + for i in range((dec_place) // 2): digit1 = (num // (10 ** i)) % (10 ** (i + 1)) digit2 = (num % (10 ** (dec_place - i + 1))) // (10 ** (dec_place - i)) - - if (digit1 != digit2): + + if digit1 != digit2: return False # if the number of digits is even, the middle number is included in comparison else: # checking if the number is a palindrome - for i in range((dec_place)//2 + 1): + for i in range((dec_place) // 2 + 1): digit1 = (num // (10 ** i)) % 10 digit2 = (num % (10 ** (dec_place - i + 1))) // (10 ** (dec_place - i)) - - if (digit1 != digit2): + + if digit1 != digit2: return False - + # returning True if all the checks for palindrome passes return True + # DRIVER CODE print(pal_check(235)) print(pal_check(121)) print(pal_check(888)) print(pal_check(1661)) -print(pal_check(678)) \ No newline at end of file +print(pal_check(678)) diff --git a/Solutions/203.py b/Solutions/203.py index bfc439c..52999a1 100644 --- a/Solutions/203.py +++ b/Solutions/203.py @@ -1,4 +1,4 @@ -''' +""" Problem: Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. @@ -8,28 +8,29 @@ Input = [5, 7, 10, 3, 4] Output = 3 -''' +""" # helper function to perform the computation def find_pivot_helper(arr, low, high): # base case for recursion - if (low == high): + if low == high: return high - + # getting the mid mid = (high + low) // 2 # checking if the mid is the pivot - if (mid < high and arr[mid] > arr[mid + 1]): + if mid < high and arr[mid] > arr[mid + 1]: return mid # checking if mid-1 is the pivot - elif (mid > low and arr[mid] < arr[mid - 1]): - return (mid - 1) + elif mid > low and arr[mid] < arr[mid - 1]: + return mid - 1 # checking if the pivot is on the right of mid - elif (arr[mid] > arr[high]): - return find_pivot_helper(arr, mid+1, high) + elif arr[mid] > arr[high]: + return find_pivot_helper(arr, mid + 1, high) # if the pivot is on the left of mid - return find_pivot_helper(arr, low, mid-1) + return find_pivot_helper(arr, low, mid - 1) + # FUNCTION TO PERFORM THE OPERATION def find_pivot(arr): @@ -38,7 +39,8 @@ def find_pivot(arr): # finding the pivot piv = find_pivot_helper(arr, 0, length) # returning the 1st index in the pivoted array - return ((piv + 1) % length) + return (piv + 1) % length + # DRIVER CODE -print(find_pivot([5, 7, 10, 3, 4])) \ No newline at end of file +print(find_pivot([5, 7, 10, 3, 4])) diff --git a/Solutions/204.py b/Solutions/204.py index ae33ed0..4e6dd1b 100644 --- a/Solutions/204.py +++ b/Solutions/204.py @@ -1,60 +1,70 @@ -''' +""" Problem: Given a complete binary tree, count the number of nodes in faster than O(n) time. Recall that a complete binary tree has every level filled except the last, and the nodes in the last level are filled starting from the left. -''' +""" # local import from the Datastructure class from DataStructures.Tree import Binary_Tree, Node # helper function to get the number of nodes -def get_num_node_complete_bin_tree_helper(self, left_route_levels=0, right_route_levels=0): +def get_num_node_complete_bin_tree_helper( + self, left_route_levels=0, right_route_levels=0 +): # getting the number of levels in the left sub-tree (runs in the 1st call only) - if (not left_route_levels): + if not left_route_levels: node = self - while (node): + while node: node = node.left left_route_levels += 1 - + # getting the number of levels in the right sub-tree (runs in the 1st call only) - if (not right_route_levels): + if not right_route_levels: node = self - while (node): + while node: node = node.right right_route_levels += 1 - + # checking if the binary tree is completely filled - if (left_route_levels == right_route_levels): + if left_route_levels == right_route_levels: return 2 ** left_route_levels - 1 - + # getting the number of nodes in the left sub-tree - if (self.left): - left_route_nodes = self.left.get_num_node_complete_bin_tree_helper(left_route_levels-1, 0) + if self.left: + left_route_nodes = self.left.get_num_node_complete_bin_tree_helper( + left_route_levels - 1, 0 + ) else: left_route_nodes = 0 # getting the number of nodes in the right sub-tree - if (self.right): - right_route_nodes = self.right.get_num_node_complete_bin_tree_helper(0, right_route_levels-1) + if self.right: + right_route_nodes = self.right.get_num_node_complete_bin_tree_helper( + 0, right_route_levels - 1 + ) else: right_route_nodes = 0 # returning the total nodes in the current sub-tree return left_route_nodes + right_route_nodes + 1 + # adding the function to the Node class -setattr(Node, 'get_num_node_complete_bin_tree_helper', get_num_node_complete_bin_tree_helper) +setattr( + Node, "get_num_node_complete_bin_tree_helper", get_num_node_complete_bin_tree_helper +) # FUNCTION TO PERFORM THE OPERATION def get_num_node_complete_bin_tree(tree): # returning 0 if the tree is empty - if (not tree.root): + if not tree.root: return 0 # getting the number of nodes using the helper function return tree.root.get_num_node_complete_bin_tree_helper() + # DRIVER CODE tree = Binary_Tree() @@ -67,4 +77,4 @@ def get_num_node_complete_bin_tree(tree): tree.root.left.right = Node(5) tree.root.right.left = Node(6) -print(get_num_node_complete_bin_tree(tree)) \ No newline at end of file +print(get_num_node_complete_bin_tree(tree)) diff --git a/Solutions/205.py b/Solutions/205.py index efe4ec3..6c1b9a1 100644 --- a/Solutions/205.py +++ b/Solutions/205.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an integer, find the next permutation of it in absolute order. @@ -7,7 +7,7 @@ Input = 48975 Output = 49578 -''' +""" # function used in problem 95 (used as a helper function in this problem) def get_next_helper(arr): @@ -15,17 +15,17 @@ def get_next_helper(arr): length = len(arr) # if arr has 0 or 1 elements, its returned - if (length < 2): + if length < 2: return arr # looping arr from the end to the beginning for index in range(length - 1, -1, -1): # finding the last element arranged in ascending order - if (index > 0 and arr[index - 1] < arr[index]): + if index > 0 and arr[index - 1] < arr[index]: break # if index is 0 (arr is sorted in descending order), arr is reversed - if (index == 0): + if index == 0: arr.reverse() else: @@ -33,8 +33,8 @@ def get_next_helper(arr): # looping over arr from the end to the index for k in range(length - 1, index - 1, -1): # getting the element to swap - if (arr[k] > arr[index - 1]): - arr[k], arr[index - 1] = arr[index - 1], arr[k] + if arr[k] > arr[index - 1]: + arr[k], arr[index - 1] = arr[index - 1], arr[k] break # arranging the other elements in proper order @@ -44,9 +44,11 @@ def get_next_helper(arr): return arr + # FUNCTION TO PERFORM THE OPERATION def get_next(num): return int("".join(get_next_helper(list(str(num))))) + # DRIVER CODE -print(get_next(48975)) \ No newline at end of file +print(get_next(48975)) diff --git a/Solutions/206.py b/Solutions/206.py index 365adb1..cc79fa6 100644 --- a/Solutions/206.py +++ b/Solutions/206.py @@ -1,4 +1,4 @@ -''' +""" Problem: A permutation can be specified by an array P, where P[i] represents the location of the element at i in the permutation. @@ -10,7 +10,7 @@ Array = ["a", "b", "c"] Permutation = [2, 1, 0] Output = ["c", "b", "a"] -''' +""" # FUNCTION TO PERFORM THE OPERATION def permute(arr, p): @@ -20,10 +20,11 @@ def permute(arr, p): # updating p to hold the result for i in range(length): p[i] = arr[p[i]] - + # returning p return p + # DRIVER CODE print(permute(["a", "b", "c"], [2, 1, 0])) -print(permute(['a', 'b', 'c', 'd'], [2, 1, 0, 3])) \ No newline at end of file +print(permute(["a", "b", "c", "d"], [2, 1, 0, 3])) diff --git a/Solutions/207.py b/Solutions/207.py index e9592d9..708f606 100644 --- a/Solutions/207.py +++ b/Solutions/207.py @@ -1,9 +1,9 @@ -''' +""" Problem: Given an undirected graph G, check whether it is bipartite. Recall that a graph is bipartite if its vertices can be divided into two independent sets, U and V, such that no edge connects vertices of the same set. -''' +""" # local import from the Datastructure module from DataStructures.Graph import Graph_Undirected_Unweighted @@ -15,15 +15,13 @@ def check_bipartite(self): # getting the nodes (sorted in reversed order) sorted_nodes = sorted( - self.connections.items(), - key=lambda x: len(x[1]), - reverse=True - ) - + self.connections.items(), key=lambda x: len(x[1]), reverse=True + ) + # iterating through the sorted nodes for node, _ in sorted_nodes: # if the node is in the 2nd set, we skip the loop - if (node in set_2): + if node in set_2: continue # else we add it to the 1st set @@ -36,14 +34,15 @@ def check_bipartite(self): # checking if all the node in the 2nd set has their connections only in the 1st set for node in set_2: for other_node in self.connections[node]: - if (other_node in set_2): + if other_node in set_2: return False # returning True if the graph is bi-partite return True + # adding the function to the graph -setattr(Graph_Undirected_Unweighted, 'check_bipartite', check_bipartite) +setattr(Graph_Undirected_Unweighted, "check_bipartite", check_bipartite) # DRIVER CODE graph1 = Graph_Undirected_Unweighted() diff --git a/Solutions/208.py b/Solutions/208.py index 60da2b5..8177665 100644 --- a/Solutions/208.py +++ b/Solutions/208.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a linked list of numbers and a pivot k, partition the linked list so that all nodes less than k come before nodes greater than or equal to k. @@ -8,7 +8,7 @@ Linked List = 5 -> 1 -> 8 -> 0 -> 3 k = 3 Output = 1 -> 0 -> 5 -> 8 -> 3 -''' +""" # local import from the Datastructre module from DataStructures.LinkedList import Node, Linked_list @@ -21,14 +21,15 @@ def pivot(self, k): # using the 2 pointers to swap the values for _ in range(self.length): - if (ptr2.val < k): + if ptr2.val < k: ptr1.val, ptr2.val = ptr2.val, ptr1.val ptr1 = ptr1.next # iterating through the linked list ptr2 = ptr2.next + # adding the pivot function to the Linked List class -setattr(Linked_list, 'pivot', pivot) +setattr(Linked_list, "pivot", pivot) # DRIVER CODE LL = Linked_list() @@ -42,4 +43,4 @@ def pivot(self, k): LL.pivot(3) -print(LL) \ No newline at end of file +print(LL) diff --git a/Solutions/209.py b/Solutions/209.py index c3a67bc..6c1b9f4 100644 --- a/Solutions/209.py +++ b/Solutions/209.py @@ -1,4 +1,4 @@ -''' +""" Problem: Write a program that computes the length of the longest common subsequence of three given strings. @@ -7,7 +7,7 @@ Input = "epidemiologist", "refrigeration", "supercalifragilisticexpialodocious" Output = 5 (since the longest common subsequence is "eieio") -''' +""" # FUNCTION TO PERFORM THE OPERATION def lcs_of_3(str1, str2, str3): @@ -18,28 +18,28 @@ def lcs_of_3(str1, str2, str3): # creating the 3d matrix for dp dp_matrix = [ - [[0 for i in range(str3_length+1)] - for j in range(str2_length+1)] - for k in range(str1_length+1) - ] + [[0 for i in range(str3_length + 1)] for j in range(str2_length + 1)] + for k in range(str1_length + 1) + ] # generating the matrix in bottom up fashion # loops start from 1 as if any of the string is empty, there is no common sub-sequence - for i in range(1, str1_length+1): - for j in range(1, str2_length+1): - for k in range(1, str3_length+1): + for i in range(1, str1_length + 1): + for j in range(1, str2_length + 1): + for k in range(1, str3_length + 1): # if a match occours, the data is updated - if (str1[i-1] == str2[j-1] and str1[i-1] == str3[k-1]): - dp_matrix[i][j][k] = dp_matrix[i-1][j-1][k-1] + 1 + if str1[i - 1] == str2[j - 1] and str1[i - 1] == str3[k - 1]: + dp_matrix[i][j][k] = dp_matrix[i - 1][j - 1][k - 1] + 1 # in case of no match, the maximum result for the part before the current position is selected else: dp_matrix[i][j][k] = max( - max(dp_matrix[i-1][j][k], dp_matrix[i][j-1][k]), - dp_matrix[i][j][k-1] - ) + max(dp_matrix[i - 1][j][k], dp_matrix[i][j - 1][k]), + dp_matrix[i][j][k - 1], + ) # returning the length of the longest common subsequence return dp_matrix[str1_length][str2_length][str3_length] + # DRIVER CODE -print(lcs_of_3("epidemiologist", "refrigeration", "supercalifragilisticexpialodocious")) \ No newline at end of file +print(lcs_of_3("epidemiologist", "refrigeration", "supercalifragilisticexpialodocious")) diff --git a/Solutions/21.py b/Solutions/21.py index ae1a6df..f8897b5 100644 --- a/Solutions/21.py +++ b/Solutions/21.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of time intervals (start, end) for classroom lectures (possibly overlapping), find the minimum number of rooms required. @@ -7,7 +7,7 @@ Input = [(30, 75), (0, 50), (60, 150)] Output = 2 -''' +""" # FUNCTION TO PERFORM THE OPERATION def find_num_rooms(intervals): @@ -17,13 +17,13 @@ def find_num_rooms(intervals): # Populating the dictionary for v in intervals: # If the start is already in the dictionary, its value is incremented, else its set to 1 - if (v[0] in D): + if v[0] in D: D[v[0]] = D[v[0]] + 1 else: - D[v[0]] = 1 - + D[v[0]] = 1 + # If the end is already in the dictionary, its value is decremented, else its set to -1 - if (v[1] in D): + if v[1] in D: D[v[1]] = D[v[1]] - 1 else: D[v[1]] = -1 @@ -34,17 +34,18 @@ def find_num_rooms(intervals): max_rooms = 0 rooms = 0 - # Looping over the events and checking the number of rooms required + # Looping over the events and checking the number of rooms required # If a class ends, the value in the dict is -ve, so upon addition, it reduces the number of rooms required for k, v in sorted_events: rooms += v # If the number of rooms required surpasses the maximum number of rooms required, max_rooms is set using the value of rooms - if (rooms > max_rooms): + if rooms > max_rooms: max_rooms = rooms - + return max_rooms + # DRIVER CODE lectures = [(30, 75), (0, 50), (60, 150)] -print('Max Rooms needed:', find_num_rooms(lectures)) \ No newline at end of file +print("Max Rooms needed:", find_num_rooms(lectures)) diff --git a/Solutions/210.py b/Solutions/210.py index 6094c75..09084ad 100644 --- a/Solutions/210.py +++ b/Solutions/210.py @@ -1,4 +1,4 @@ -''' +""" Problem: A Collatz sequence in mathematics can be defined as follows. @@ -8,37 +8,38 @@ It is conjectured that every such sequence eventually reaches the number 1. Test this conjecture. Bonus: What input n <= 1000000 gives the longest sequence? -''' +""" # function to calculate the number of numbers in the current sequence -# function optimized for checking all numbers in a range using cache +# function optimized for checking all numbers in a range using cache # (hard-coded range is 1 to 1000000) def collatz_seq(num, cache, i, acc=0): # base case for recursion - if (num == 1): + if num == 1: return acc - + # checking in cache if the number is in cache range - if (num < 1000000): + if num < 1000000: # checking if the data is in cache - if (cache[i] != -1): + if cache[i] != -1: return cache[i] # else generating the data and storing in the cache else: - if (num % 2 == 0): - temp = collatz_seq(num//2, cache, i, acc+1) + if num % 2 == 0: + temp = collatz_seq(num // 2, cache, i, acc + 1) cache[i] = temp return temp else: - temp = collatz_seq(3*num+1, cache, i, acc+1) + temp = collatz_seq(3 * num + 1, cache, i, acc + 1) cache[i] = temp return temp # generating the value if its outside the cache range else: - if (num % 2 == 0): - return collatz_seq(num//2, cache, i, acc+1) + if num % 2 == 0: + return collatz_seq(num // 2, cache, i, acc + 1) else: - return collatz_seq(3*num+1, cache, i, acc+1) + return collatz_seq(3 * num + 1, cache, i, acc + 1) + # FUNCTION TO PERFORM THE OPERATION def get_longest_collatz_seq(): @@ -55,11 +56,12 @@ def get_longest_collatz_seq(): temp_sequence = collatz_seq(i, cache, i, 0) # updating the longest_sequence and longest_sequence_value as per requirement - if (temp_sequence > longest_sequence): + if temp_sequence > longest_sequence: longest_sequence = temp_sequence longest_sequence_value = i # returning number of numbers in the longest sequence return longest_sequence_value + # DRIVER CODE -print(get_longest_collatz_seq()) \ No newline at end of file +print(get_longest_collatz_seq()) diff --git a/Solutions/211.py b/Solutions/211.py index cbffa54..f4d4833 100644 --- a/Solutions/211.py +++ b/Solutions/211.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string and a pattern, find the starting indices of all occurrences of the pattern in the string. @@ -8,7 +8,7 @@ String = "abracadabra" Pattern = "abr" Output = [0, 7] -''' +""" # FUNCTION TO PERFORM THE OPERATION def KMPSearch(string, pattern): @@ -20,37 +20,38 @@ def KMPSearch(string, pattern): lps = [0] * patten_length # array to store the results result = [] - - j = 0 # index for patten - i = 0 # index for string + + j = 0 # index for patten + i = 0 # index for string # preprocessing the pattern (computing the lps array) compute_LPS(pattern, patten_length, lps) # iterating through the string - while (i < string_length): + while i < string_length: # if match occours i & j are incremented - if (pattern[j] == string[i]): + if pattern[j] == string[i]: i += 1 j += 1 # if the entire pattern matches - if (j == patten_length): - # adding the position to result & going back to the required location + if j == patten_length: + # adding the position to result & going back to the required location # (based upon the pre-processed array) result.append(i - j) j = lps[j - 1] # mismatch after j matches - elif (i < string_length and pattern[j] != string[i]): + elif i < string_length and pattern[j] != string[i]: # going back to the required location (based upon the pre-processed array) or incrementing i - if (j != 0): - j = lps[j-1] + if j != 0: + j = lps[j - 1] else: i += 1 # returning the result return result + # helper function to pre-process the array def compute_LPS(pattern, patten_length, lps): # length of the previous longest prefix suffix (initialized as 0) @@ -61,23 +62,24 @@ def compute_LPS(pattern, patten_length, lps): i = 1 # generating the lps array - while (i < patten_length): + while i < patten_length: # match occours - if (pattern[i]== pattern[length]): + if pattern[i] == pattern[length]: length += 1 lps[i] = length i += 1 # match doesn't occour else: # if the prefix match is postive its updated to the previous value in lps - if (length != 0): - length = lps[length-1] + if length != 0: + length = lps[length - 1] # if prefix match is 0, lps for the value is set to 0 and i incremented else: lps[i] = 0 i += 1 + # DRIVER CODE print(KMPSearch("abracadabra", "abr")) print(KMPSearch("abracadabra", "xyz")) -print(KMPSearch("aaaa", "aa")) \ No newline at end of file +print(KMPSearch("aaaa", "aa")) diff --git a/Solutions/212.py b/Solutions/212.py index 8d47888..90fcbee 100644 --- a/Solutions/212.py +++ b/Solutions/212.py @@ -1,4 +1,4 @@ -''' +""" Problem: Spreadsheets often use this alphabetical encoding for its columns: "A", "B", "C", ..., "AA", "AB", ..., "ZZ", "AAA", "AAB", .... @@ -11,7 +11,7 @@ Input = 27 Output = "AA" -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_col_name(num): @@ -19,15 +19,16 @@ def get_col_name(num): result = "" # generating the result from the last character to the 1st - while (num > 0): + while num > 0: result = chr(64 + (num % 26)) + result num = num // 26 - + # returning the result return result + # DRIVER CODE print(get_col_name(1)) print(get_col_name(27)) print(get_col_name(30)) -print(get_col_name(53)) \ No newline at end of file +print(get_col_name(53)) diff --git a/Solutions/213.py b/Solutions/213.py index af97240..3b39dcf 100644 --- a/Solutions/213.py +++ b/Solutions/213.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string of digits, generate all possible valid IP address combinations. @@ -9,7 +9,7 @@ Input = "2542540123" Output = ['254.25.40.123', '254.254.0.123'] -''' +""" # generating the set of acceptable numbers ACCEPTABLE_NUMBERS = set([str(i) for i in range(256)]) @@ -18,13 +18,13 @@ def get_ip_combinations_helper(string, curr, accumulator): # if the end of the string is reached and a proper ip config is generated # the combination is added to the accumulator - if (not string and len(curr) == 4): + if not string and len(curr) == 4: accumulator.append(list(curr)) return # if the combination is not correct, its not added to the accumulator - elif (len(curr) > 4): + elif len(curr) > 4: return - + # declaring the current part curr_part = "" @@ -36,12 +36,15 @@ def get_ip_combinations_helper(string, curr, accumulator): # getting the length of the current part length = len(curr_part) # if the length is more than acceptable, the function breaks out - if (length > 3): + if length > 3: return - - # if the current part is an acceptable number, get_ip_combinations_helper is called recursively - if (curr_part in ACCEPTABLE_NUMBERS): - get_ip_combinations_helper(string[length:], list(curr) + [curr_part], accumulator) + + # if the current part is an acceptable number, get_ip_combinations_helper is called recursively + if curr_part in ACCEPTABLE_NUMBERS: + get_ip_combinations_helper( + string[length:], list(curr) + [curr_part], accumulator + ) + # FUNCTION TO PERFORM THE OPERATION def get_ip_combinations(string): @@ -52,5 +55,6 @@ def get_ip_combinations(string): # returning the ip configurations in the proper format return [".".join(combination) for combination in accumulator] + # DRIVER CODE -print(get_ip_combinations("2542540123")) \ No newline at end of file +print(get_ip_combinations("2542540123")) diff --git a/Solutions/214.py b/Solutions/214.py index 64cda84..20941ff 100644 --- a/Solutions/214.py +++ b/Solutions/214.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an integer n, return the length of the longest consecutive run of 1s in its binary representation. @@ -7,7 +7,7 @@ Input = 156 Output = 3 -''' +""" # FUNCTION TO PERFORM THE OPERATION def longest_chain_of_1(num): @@ -21,15 +21,16 @@ def longest_chain_of_1(num): # iterating through the binary number for i in num: # updating chain max and chain curr - if (i == '1'): + if i == "1": chain_curr += 1 else: chain_max = max(chain_max, chain_curr) chain_curr = 0 - + # returning the result return max(chain_max, chain_curr) + # DRIVER CODE print(longest_chain_of_1(15)) -print(longest_chain_of_1(156)) \ No newline at end of file +print(longest_chain_of_1(156)) diff --git a/Solutions/215.py b/Solutions/215.py index 8b4578c..6851849 100644 --- a/Solutions/215.py +++ b/Solutions/215.py @@ -1,4 +1,4 @@ -''' +""" Problem: The horizontal distance of a binary tree node describes how far left or right the node will be when the tree is printed out. @@ -19,7 +19,7 @@ Given the root to a binary tree, return its bottom view. For this tree, for example, the bottom view could be [0, 1, 3, 6, 8, 9]. -''' +""" # importing from the local Datastructure module from DataStructures.Tree import Node, Binary_Tree @@ -27,26 +27,27 @@ # helper function to construct the bottom view def get_bottom_view_helper(node, depth, hd, accumulator): # checking and adding the depth and value of the node as per requirement - if (hd not in accumulator): + if hd not in accumulator: accumulator[hd] = (depth, node.val) else: - if (accumulator[hd][0] < depth): + if accumulator[hd][0] < depth: accumulator[hd] = (depth, node.val) # recursively calling the function for the children if they exist - if (node.left): - get_bottom_view_helper(node.left, depth+1, hd-1, accumulator) - if (node.right): - get_bottom_view_helper(node.right, depth+1, hd+1, accumulator) - + if node.left: + get_bottom_view_helper(node.left, depth + 1, hd - 1, accumulator) + if node.right: + get_bottom_view_helper(node.right, depth + 1, hd + 1, accumulator) + # returning the accumulator return accumulator + # FUNCTION TO PERFORM THE OPERATION def get_bottom_view(tree): # getting the depth and value of each node by horizontal distance data = get_bottom_view_helper(tree.root, 0, 0, {}) - + # creating a array for the data by the deepest nodes' horizontal distance res_arr = [(hd, data[hd][1]) for hd in data] # sorting the list by horizontal distance @@ -55,6 +56,7 @@ def get_bottom_view(tree): # returning the bottom view (only the values) return [elem for _, elem in res_arr] + # DRIVER CODE tree = Binary_Tree() tree.root = Node(5) @@ -73,4 +75,4 @@ def get_bottom_view(tree): tree.root.right.right.left = Node(8) print(tree) -print(get_bottom_view(tree)) \ No newline at end of file +print(get_bottom_view(tree)) diff --git a/Solutions/216.py b/Solutions/216.py index 5d33de7..239bf98 100644 --- a/Solutions/216.py +++ b/Solutions/216.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a number in Roman numeral format, convert it to decimal. @@ -18,21 +18,13 @@ Input = XIV Output = 14 -''' +""" # global map for the Roman numbers -VALUE_MAP = { - 'M': 1000, - 'D': 500, - 'C': 100, - 'L': 50, - 'X': 10, - 'V': 5, - 'I': 1 -} +VALUE_MAP = {"M": 1000, "D": 500, "C": 100, "L": 50, "X": 10, "V": 5, "I": 1} # FUNCTION TO PERFORM THE OPERATION -def convert_roman_to_decimal(num_str:str) -> int: +def convert_roman_to_decimal(num_str: str) -> int: # declaring the map global VALUE_MAP @@ -40,20 +32,21 @@ def convert_roman_to_decimal(num_str:str) -> int: num = 0 # iterating through the Roman number - for i in range(length-1): + for i in range(length - 1): # checking whether the value has to be added or subtracted and performing the operation - if (VALUE_MAP[num_str[i]] < VALUE_MAP[num_str[i+1]]): + if VALUE_MAP[num_str[i]] < VALUE_MAP[num_str[i + 1]]: num -= VALUE_MAP[num_str[i]] else: num += VALUE_MAP[num_str[i]] - + # since the loop goes till length-1, adding the last value - num += VALUE_MAP[num_str[length-1]] + num += VALUE_MAP[num_str[length - 1]] return num + # DRIVER CODE print(convert_roman_to_decimal("I")) print(convert_roman_to_decimal("IV")) print(convert_roman_to_decimal("XIV")) -print(convert_roman_to_decimal("XL")) \ No newline at end of file +print(convert_roman_to_decimal("XL")) diff --git a/Solutions/217.py b/Solutions/217.py index c6c9d83..d78b89d 100644 --- a/Solutions/217.py +++ b/Solutions/217.py @@ -1,11 +1,11 @@ -''' +""" Problem: We say a number is sparse if there are no adjacent ones in its binary representation. Do this in faster than O(N log N) time. For a given input N, find the smallest sparse number greater than or equal to N. For example, 21 (10101) is sparse, but 22 (10110) is not. -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_next_sparse(num): @@ -16,25 +16,26 @@ def get_next_sparse(num): flag = False for i, digit in enumerate(binary): - if (digit == '1' and prev_digit == '1'): + if digit == "1" and prev_digit == "1": flag = True - if (flag): - new_str_bin += '0' * (len(binary) - i) + if flag: + new_str_bin += "0" * (len(binary) - i) break else: new_str_bin += digit prev_digit = digit - if (flag): - if (new_str_bin[0] == '1'): - new_str_bin = '10' + new_str_bin[1:] + if flag: + if new_str_bin[0] == "1": + new_str_bin = "10" + new_str_bin[1:] else: - new_str_bin = '1' + new_str_bin + new_str_bin = "1" + new_str_bin return int(new_str_bin, base=2) + # DRIVER CODE print(get_next_sparse(21)) print(get_next_sparse(25)) -print(get_next_sparse(255)) \ No newline at end of file +print(get_next_sparse(255)) diff --git a/Solutions/218.py b/Solutions/218.py index c7bf7a8..3a4a9e2 100644 --- a/Solutions/218.py +++ b/Solutions/218.py @@ -1,9 +1,9 @@ -''' +""" Problem: Write an algorithm that computes the reversal of a directed graph. For example, if a graph consists of A -> B -> C, it should become A <- B <- C. -''' +""" # local import from Datastructure module from DataStructures.Graph import Graph_Directed_Unweighted @@ -14,22 +14,22 @@ def reverse_direction(self): visited = set() for node in self.connections: - # storing the nodes that require updation in to change as for loop doesn't + # storing the nodes that require updation in to change as for loop doesn't # support simultaneous updation visited.add(node) to_change = [] for neighbour in self.connections[node]: - if (neighbour not in visited): - if (node not in self.connections[neighbour]): + if neighbour not in visited: + if node not in self.connections[neighbour]: to_change.append(neighbour) - + for neighbour in to_change: self.connections[neighbour].add(node) self.connections[node].remove(neighbour) -setattr(Graph_Directed_Unweighted, 'reverse_direction', reverse_direction) +setattr(Graph_Directed_Unweighted, "reverse_direction", reverse_direction) # DRIVER CODE graph = Graph_Directed_Unweighted() @@ -41,4 +41,4 @@ def reverse_direction(self): graph.reverse_direction() -print(graph) \ No newline at end of file +print(graph) diff --git a/Solutions/219.py b/Solutions/219.py index 7a084cd..4f854e8 100644 --- a/Solutions/219.py +++ b/Solutions/219.py @@ -1,105 +1,105 @@ -''' +""" Problem: Connect 4 is a game where opponents take turns dropping red or black discs into a 7 x 6 vertically suspended grid. The game ends either when one player creates a line of four consecutive discs of their color (horizontally, vertically, or diagonally), or when there are no more spots left in the grid. Design and implement Connect 4. -''' +""" class Connect4: def __init__(self): self.board = [["-" for _ in range(7)] for _ in range(6)] self.to_play = "R" - + def get_empty(self, position): if self.board[0][position] != "-": return -1 if self.board[5][position] == "-": return 5 - + for i in range(5): - if self.board[i][position] == "-" and self.board[i+1][position] != "-": + if self.board[i][position] == "-" and self.board[i + 1][position] != "-": return i - + def play_turn(self): - position = int(input('Enter the location to put the disk: ')) + position = int(input("Enter the location to put the disk: ")) position -= 1 row = self.get_empty(position) - while (row == -1): - position = int(input('Enter the location to put the disk: ')) + while row == -1: + position = int(input("Enter the location to put the disk: ")) position -= 1 row = self.get_empty(position) - + if self.to_play == "R": self.board[row][position] = "R" self.to_play = "B" else: self.board[row][position] = "B" self.to_play = "R" - + def victory_check(self): for i in range(6): for j in range(4): if self.board[i][j] in ("R", "B"): disk = self.board[i][j] - for k in range(j, j+4): + for k in range(j, j + 4): if self.board[i][k] != disk: break else: return disk - + for i in range(3): for j in range(7): if self.board[i][j] in ("R", "B"): disk = self.board[i][j] - for k in range(i, i+4): + for k in range(i, i + 4): if self.board[k][j] != disk: break else: return disk - + for i in range(2): for j in range(3): if self.board[i][j] in ("R", "B"): disk = self.board[i][j] for k in range(4): - if self.board[i+k][j+k] != disk: + if self.board[i + k][j + k] != disk: break else: return disk - + for i in range(3, 6): for j in range(4, 7): if self.board[i][j] in ("R", "B"): disk = self.board[i][j] for k in range(4): - if self.board[i-k][j-k] != disk: + if self.board[i - k][j - k] != disk: break else: return disk - + return None - + def full_check(self): for i in range(6): for j in range(7): if self.board[i][j] == "-": return False - + return True - + def print_board(self): for i in range(6): for j in range(7): print(self.board[i][j], end=" ") print() - + def play(self): while not self.full_check() and not self.victory_check(): print(self.to_play, "to play") @@ -107,7 +107,7 @@ def play(self): print("Board: ") self.print_board() print() - + if self.full_check(): print("Its a draw") else: @@ -115,4 +115,4 @@ def play(self): # DRIVER CODE -Connect4().play() \ No newline at end of file +Connect4().play() diff --git a/Solutions/22.py b/Solutions/22.py index 662f869..2bcb939 100644 --- a/Solutions/22.py +++ b/Solutions/22.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a dictionary of words and a string made up of those words (no spaces), return the original sentence in a list. @@ -12,7 +12,7 @@ Input = ['bed', 'bath', 'bedbath', 'and', 'beyond'], "bedbathandbeyond" Output = ['bed', 'bath', 'and', 'beyond] OR ['bedbath', 'and', 'beyond'] -''' +""" # FUNCTION TO PERFORM THE OPERATION def words(List, string): @@ -32,17 +32,18 @@ def words(List, string): buffer += i # If the word in the buffer is in the set, it is added to the found list and buffer reset - if (buffer in Set): + if buffer in Set: found.append(buffer) buffer = "" - + # If no word is found, None is returned - if (len(found) == 0): + if len(found) == 0: return None return found + # DRIVER CODE -print(words(['quick', 'brown', 'the', 'fox'], "thequickbrownfox")) -print(words(['bed', 'bath', 'bedbath', 'and', 'beyond'], "bedbathandbeyond")) -print(words(['quick', 'brown', 'the', 'fox'], "bedbathandbeyond")) \ No newline at end of file +print(words(["quick", "brown", "the", "fox"], "thequickbrownfox")) +print(words(["bed", "bath", "bedbath", "and", "beyond"], "bedbathandbeyond")) +print(words(["quick", "brown", "the", "fox"], "bedbathandbeyond")) diff --git a/Solutions/220.py b/Solutions/220.py index cf4c5a1..d0fc25f 100644 --- a/Solutions/220.py +++ b/Solutions/220.py @@ -1,26 +1,28 @@ -''' +""" Problem: In front of you is a row of N coins, with values v_1, v_2, ..., v_n. You are asked to play the following game. You and an opponent take turns choosing either the first or last coin from the row, removing it from the row, and receiving the value of the coin. Write a program that returns the maximum amount of money you can win with certainty, if you move first, assuming your opponent plays optimally. -''' +""" # FUNCTION TO PERFORM THE OPERATION def optimal_strategy_of_game(coins_arr, amount=0, to_play=True): if not coins_arr: return amount - + if to_play: return max( - optimal_strategy_of_game(coins_arr[1:], amount+coins_arr[0], False), - optimal_strategy_of_game(coins_arr[:-1], amount+coins_arr[-1], False) + optimal_strategy_of_game(coins_arr[1:], amount + coins_arr[0], False), + optimal_strategy_of_game(coins_arr[:-1], amount + coins_arr[-1], False), ) - if coins_arr[0] > coins_arr[-1]: return optimal_strategy_of_game(coins_arr[1:], amount, True) + if coins_arr[0] > coins_arr[-1]: + return optimal_strategy_of_game(coins_arr[1:], amount, True) return optimal_strategy_of_game(coins_arr[:-1], amount, True) + # DRIVER CODE -print(optimal_strategy_of_game([1, 2, 3, 4, 5])) \ No newline at end of file +print(optimal_strategy_of_game([1, 2, 3, 4, 5])) diff --git a/Solutions/221.py b/Solutions/221.py index e19048f..ec38b3e 100644 --- a/Solutions/221.py +++ b/Solutions/221.py @@ -1,21 +1,21 @@ -''' +""" Problem: Let's define a "sevenish" number to be one which is either a power of 7, or the sum of unique powers of 7. The first few sevenish numbers are 1, 7, 8, 49, and so on. Create an algorithm to find the nth sevenish number. -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_sevenish_num(number): curr = 1 curr_iteration = 1 - while (curr < number): + while curr < number: curr_iteration += 1 curr += curr_iteration - + curr -= curr_iteration - + result = 7 ** (curr_iteration - 1) curr_to_add = 1 @@ -27,9 +27,9 @@ def get_sevenish_num(number): # DRIVER CODE -print(get_sevenish_num(1)) # 1 = 7 ^ 0 -print(get_sevenish_num(2)) # 7 = 7 ^ 1 -print(get_sevenish_num(3)) # 8 = 7 ^ 0 + 7 ^ 1 -print(get_sevenish_num(4)) # 49 = 7 ^ 2 -print(get_sevenish_num(5)) # 50 = 7 ^ 0 + 7 ^ 2 -print(get_sevenish_num(6)) # 57 = 7 ^ 0 + 7 ^ 1 + 7 ^ 2 \ No newline at end of file +print(get_sevenish_num(1)) # 1 = 7 ^ 0 +print(get_sevenish_num(2)) # 7 = 7 ^ 1 +print(get_sevenish_num(3)) # 8 = 7 ^ 0 + 7 ^ 1 +print(get_sevenish_num(4)) # 49 = 7 ^ 2 +print(get_sevenish_num(5)) # 50 = 7 ^ 0 + 7 ^ 2 +print(get_sevenish_num(6)) # 57 = 7 ^ 0 + 7 ^ 1 + 7 ^ 2 diff --git a/Solutions/222.py b/Solutions/222.py index f27caf0..85e26c3 100644 --- a/Solutions/222.py +++ b/Solutions/222.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an absolute pathname that may have . or .. as part of it, return the shortest standardized path. @@ -7,23 +7,23 @@ Input = "/usr/bin/../bin/./scripts/../" Output = "/usr/bin/" -''' +""" def get_shortest_standardized_path(path): - path_list = path.split('/') + path_list = path.split("/") stack = [] for curr in path_list: - if (curr == '..'): + if curr == "..": stack.pop() - elif (curr == '.'): + elif curr == ".": continue else: stack.append(curr) - + return "/".join(stack) if __name__ == "__main__": - print(get_shortest_standardized_path("/usr/bin/../bin/./scripts/../")) \ No newline at end of file + print(get_shortest_standardized_path("/usr/bin/../bin/./scripts/../")) diff --git a/Solutions/223.py b/Solutions/223.py index 2b6740a..376849c 100644 --- a/Solutions/223.py +++ b/Solutions/223.py @@ -1,14 +1,14 @@ -''' +""" Problem: Typically, an implementation of in-order traversal of a binary tree has O(h) space complexity, where h is the height of the tree. Write a program to compute the in-order traversal of a binary tree using O(1) space. -''' +""" from DataStructures.Tree import Binary_Tree, Node -def morris_traversal(tree): +def morris_traversal(tree): current = tree.root while current is not None: @@ -16,7 +16,7 @@ def morris_traversal(tree): yield current.val current = current.right else: - # Find the inorder predecessor of current + # Find the inorder predecessor of current pre = current.left while pre.right is not None and pre.right is not current: pre = pre.right @@ -50,4 +50,4 @@ def morris_traversal(tree): print(tree) for node in morris_traversal(tree): - print(node, end=" ") \ No newline at end of file + print(node, end=" ") diff --git a/Solutions/224.py b/Solutions/224.py index 2caffad..87f92fe 100644 --- a/Solutions/224.py +++ b/Solutions/224.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a sorted array, find the smallest positive integer that is not the sum of a subset of the array. @@ -8,20 +8,20 @@ Input = [1, 2, 3, 10] Output = 7 -''' +""" def find_smallest_subset_sum_not_in_arr(arr): res = 1 for elem in arr: - if (elem > res): + if elem > res: break res += elem - + return res print(find_smallest_subset_sum_not_in_arr([1, 2, 3, 10])) print(find_smallest_subset_sum_not_in_arr([1, 2, 10])) -print(find_smallest_subset_sum_not_in_arr([1, 10])) \ No newline at end of file +print(find_smallest_subset_sum_not_in_arr([1, 10])) diff --git a/Solutions/225.py b/Solutions/225.py index 14a7ee9..e489726 100644 --- a/Solutions/225.py +++ b/Solutions/225.py @@ -1,4 +1,4 @@ -''' +""" Problem: There are N prisoners standing in a circle, waiting to be executed. @@ -11,11 +11,11 @@ N = 5 k = 2 Output = 3 (sequence will be [2, 4, 1, 5, 3]) -''' +""" def find_last(n, k): - prisoners = [i for i in range(1, n+1)] + prisoners = [i for i in range(1, n + 1)] last_executed = None curr_pos = 0 @@ -23,11 +23,11 @@ def find_last(n, k): curr_pos = (curr_pos + k - 1) % len(prisoners) last_executed = prisoners[curr_pos] - prisoners = prisoners[:curr_pos] + prisoners[curr_pos+1:] - + prisoners = prisoners[:curr_pos] + prisoners[curr_pos + 1 :] + return last_executed print(find_last(5, 2)) print(find_last(3, 2)) -print(find_last(5, 3)) \ No newline at end of file +print(find_last(5, 3)) diff --git a/Solutions/226.py b/Solutions/226.py index f75e722..0015710 100644 --- a/Solutions/226.py +++ b/Solutions/226.py @@ -1,4 +1,4 @@ -''' +""" Problem: You come across a dictionary of sorted words in a language you've never seen before. @@ -8,7 +8,7 @@ Input = ['xww', 'wxyz', 'wxyw', 'ywx', 'ywz'] Output = ['x', 'z', 'w', 'y'] -''' +""" def update_letter_order(sorted_words, letters): @@ -17,36 +17,36 @@ def update_letter_order(sorted_words, letters): prev_char = None for word in sorted_words: - if (word): + if word: char = word[0] - if (char != prev_char): + if char != prev_char: order.append(char) - if (char not in new_words): + if char not in new_words: new_words[char] = list() - + new_words[char].append(word[1:]) prev_char = char for index, char in enumerate(order): - letters[char] = letters[char] | set(order[index + 1:]) + letters[char] = letters[char] | set(order[index + 1 :]) for char in new_words: update_letter_order(new_words[char], letters) def find_path(letters, start, path, length): - if (len(path) == length): + if len(path) == length: return path - if (not letters[start]): + if not letters[start]: return None for next_start in letters[start]: new_path = find_path(letters, next_start, path + [next_start], length) - if (new_path): + if new_path: return new_path @@ -55,7 +55,7 @@ def get_letter_order(sorted_words): for word in sorted_words: for letter in word: - if (letter not in letters): + if letter not in letters: letters[letter] = set() update_letter_order(sorted_words, letters) @@ -68,10 +68,10 @@ def get_letter_order(sorted_words): for head in potential_heads: path = find_path(letters, head, path=[head], length=len(letters)) - if (path): + if path: break return path -print(get_letter_order(['xww', 'wxyz', 'wxyw', 'ywx', 'ywz'])) +print(get_letter_order(["xww", "wxyz", "wxyw", "ywx", "ywz"])) diff --git a/Solutions/227.py b/Solutions/227.py index 6f26e49..2a0c3fd 100644 --- a/Solutions/227.py +++ b/Solutions/227.py @@ -1,10 +1,10 @@ -''' +""" Problem: Boggle is a game played on a 4 x 4 grid of letters. The goal is to find as many words as possible that can be formed by a sequence of adjacent letters in the grid, using each cell at most once. Given a game board and a dictionary of valid words, implement a Boggle solver. -''' +""" from DataStructures.Trie import Trie @@ -21,11 +21,11 @@ def get_neighbours(pos): (i + 1, j + 1), (i + 1, j), (i + 1, j - 1), - (i, j - 1) + (i, j - 1), ] for y, x in all_neighbours: - if (0 <= x < 4 and 0 <= y < 4): + if 0 <= x < 4 and 0 <= y < 4: neighbours.append((y, x)) return neighbours @@ -33,16 +33,16 @@ def get_neighbours(pos): def get_words(matrix, pos, trie, curr, res): possibilities = trie.get_suggestions(curr) - if (not possibilities): + if not possibilities: return - if (len(possibilities) == 1 and list(possibilities)[0] == curr): + if len(possibilities) == 1 and list(possibilities)[0] == curr: res.add(curr) return - + for neighbour in get_neighbours(pos): i, j = neighbour - get_words(matrix, neighbour, trie, curr+matrix[i][j], res) - + get_words(matrix, neighbour, trie, curr + matrix[i][j], res) + return @@ -54,9 +54,9 @@ def solve_Boggle(matrix, dictionary): for i in range(4): for j in range(4): - if (matrix[i][j] in prefix_tree.root.children): + if matrix[i][j] in prefix_tree.root.children: get_words(matrix, (i, j), prefix_tree, matrix[i][j], res) - + return res @@ -65,15 +65,11 @@ def solve_Boggle(matrix, dictionary): ["A", "L", "B", "P"], ["C", "O", "E", "Y"], ["F", "C", "H", "O"], - ["B", "A", "D", "A"] + ["B", "A", "D", "A"], ] -words_in_board = { - "PECH", "COLA", "YO", "BAD" - } -words_not_in_board = { - "FOR", "BULL" -} +words_in_board = {"PECH", "COLA", "YO", "BAD"} +words_not_in_board = {"FOR", "BULL"} dictionary = words_in_board | words_not_in_board print(dictionary) -print(solve_Boggle(board, dictionary)) \ No newline at end of file +print(solve_Boggle(board, dictionary)) diff --git a/Solutions/228.py b/Solutions/228.py index 33325d6..5be2acc 100644 --- a/Solutions/228.py +++ b/Solutions/228.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of numbers, create an algorithm that arranges them in order to form the largest possible integer. @@ -7,26 +7,31 @@ Input = [10, 7, 76, 415] Output = 77641510 -''' +""" class ModifiedInt: # helper class for the sort operation (requires __lt__ dunder method) def __init__(self, val): - if type(val) != int: raise TypeError + if type(val) != int: + raise TypeError self.val = str(val) def __lt__(self, other): # returns the number with shorter length or has a smaller more significant digit - if (type(other) == ModifiedInt): - if (self.val == other.val): return False + if type(other) == ModifiedInt: + if self.val == other.val: + return False for c1, c2 in zip(self.val, other.val): - if (c1 > c2): return False - elif (c1 < c2): return True + if c1 > c2: + return False + elif c1 < c2: + return True - if (len(self.val) > len(other.val)): return True + if len(self.val) > len(other.val): + return True return False @@ -37,4 +42,4 @@ def get_largest(arr): # DRIVER CODE -print(get_largest([10, 7, 76, 415])) \ No newline at end of file +print(get_largest([10, 7, 76, 415])) diff --git a/Solutions/229.py b/Solutions/229.py index 0e330ec..d72219f 100644 --- a/Solutions/229.py +++ b/Solutions/229.py @@ -1,4 +1,4 @@ -''' +""" Problem: Snakes and Ladders is a game played on a 10 x 10 board, the goal of which is get from square 1 to square 100. @@ -9,14 +9,15 @@ For convenience, here are the squares representing snakes and ladders, and their outcomes: snakes = {16: 6, 48: 26, 49: 11, 56: 53, 62: 19, 64: 60, 87: 24, 93: 73, 95: 75, 98: 78} ladders = {1: 38, 4: 14, 9: 31, 21: 42, 28: 84, 36: 44, 51: 67, 71: 91, 80: 100} -''' +""" def get_next_ladder(ladders, pos): # helper function to get the position of the next ladder curr = 101 - for key in ladders: - if (key > pos and key < curr): curr = key + for key in ladders: + if key > pos and key < curr: + curr = key return curr @@ -24,8 +25,10 @@ def get_next_no_snake(snakes, pos): # helper function to get the position of the next position without snake curr = pos + 6 for _ in range(6): - if curr in snakes: curr -= 1 - else: break + if curr in snakes: + curr -= 1 + else: + break return curr @@ -40,10 +43,10 @@ def play_snake_and_ladders(snakes, ladders): pos = min(get_next_ladder(ladders, pos), get_next_no_snake(snakes, pos), 100) print(pos, end=" ") - if (pos in ladders): + if pos in ladders: pos = ladders[pos] print(f"=> {pos}", end=" ") - if (pos < 100): + if pos < 100: print("->", end=" ") print() @@ -53,4 +56,4 @@ def play_snake_and_ladders(snakes, ladders): snakes = {16: 6, 48: 26, 49: 11, 56: 53, 62: 19, 64: 60, 87: 24, 93: 73, 95: 75, 98: 78} ladders = {1: 38, 4: 14, 9: 31, 21: 42, 28: 84, 36: 44, 51: 67, 71: 91, 80: 100} -print(play_snake_and_ladders(snakes, ladders)) \ No newline at end of file +print(play_snake_and_ladders(snakes, ladders)) diff --git a/Solutions/23.py b/Solutions/23.py index f6d1bee..20926db 100644 --- a/Solutions/23.py +++ b/Solutions/23.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an M by N matrix consisting of booleans that represents a board. Each True boolean represents a wall. @@ -15,79 +15,89 @@ Start = (3, 0) End = (0, 0) Output = 7 -''' +""" # Import not mandatory (Used it to display the matrix in a prettily) -from numpy import array # Comment out the full line if you dont have numpy +from numpy import array # Comment out the full line if you dont have numpy # Helper function to do the heavy lifting def min_steps_helper(mat, pos, n, m): - # List to store all the visited neighboring locations + # List to store all the visited neighboring locations arr = [] # Adding all the values and finding the minimum - if (pos[0] < n and pos[0] >= 0 and pos[1] < m and pos[1] >= 0 and mat[pos[0]][pos[1]] != 't'): - if (pos[0] + 1 < n and mat[pos[0] + 1][pos[1]] not in ['t', 0]): + if ( + pos[0] < n + and pos[0] >= 0 + and pos[1] < m + and pos[1] >= 0 + and mat[pos[0]][pos[1]] != "t" + ): + if pos[0] + 1 < n and mat[pos[0] + 1][pos[1]] not in ["t", 0]: arr.append(mat[pos[0] + 1][pos[1]]) - if (pos[0] - 1 >= 0 and mat[pos[0] - 1][pos[1]] not in ['t', 0]): + if pos[0] - 1 >= 0 and mat[pos[0] - 1][pos[1]] not in ["t", 0]: arr.append(mat[pos[0] - 1][pos[1]]) - if (pos[1] + 1 < m and mat[pos[0]][pos[1] + 1] not in ['t', 0]): + if pos[1] + 1 < m and mat[pos[0]][pos[1] + 1] not in ["t", 0]: arr.append(mat[pos[0]][pos[1] + 1]) - if (pos[1] - 1 >= 0 and mat[pos[0]][pos[1] - 1] not in ['t', 0]): + if pos[1] - 1 >= 0 and mat[pos[0]][pos[1] - 1] not in ["t", 0]: arr.append(mat[pos[0]][pos[1] - 1]) - + # Updating the value of the present position mat[pos[0]][pos[1]] = min(arr) + 1 # Calling the funtion on each of the valid neigboring positions - if (pos[0] + 1 < n and mat[pos[0] + 1][pos[1]] == 0): - min_steps_helper(mat, (pos[0]+1, pos[1]), n, m) - if (pos[0] - 1 >= 0 and mat[pos[0] - 1][pos[1]] == 0): - min_steps_helper(mat, (pos[0]-1, pos[1]), n, m) - if (pos[1] + 1 < m and mat[pos[0]][pos[1] + 1] == 0): - min_steps_helper(mat, (pos[0], pos[1]+1), n, m) - if (pos[1] - 1 >= 0 and mat[pos[0]][pos[1] - 1] == 0): - min_steps_helper(mat, (pos[0], pos[1]-1), n, m) + if pos[0] + 1 < n and mat[pos[0] + 1][pos[1]] == 0: + min_steps_helper(mat, (pos[0] + 1, pos[1]), n, m) + if pos[0] - 1 >= 0 and mat[pos[0] - 1][pos[1]] == 0: + min_steps_helper(mat, (pos[0] - 1, pos[1]), n, m) + if pos[1] + 1 < m and mat[pos[0]][pos[1] + 1] == 0: + min_steps_helper(mat, (pos[0], pos[1] + 1), n, m) + if pos[1] - 1 >= 0 and mat[pos[0]][pos[1] - 1] == 0: + min_steps_helper(mat, (pos[0], pos[1] - 1), n, m) + # FUNCTION TO PERFORM THE OPERATION def min_steps(mat, n, m, start, stop): # Replacing the 'f's with 0's for i in range(n): for j in range(m): - if (mat[i][j] == 'f'): + if mat[i][j] == "f": mat[i][j] = 0 - + # Offseting the value by 1 (as 0 represents unvisited positions) pos = start mat[start[0]][start[1]] = 1 - + # Calling the helper function on each neighbouring position where the value is 0 try: - if (pos[0] + 1 < n and mat[pos[0] + 1][pos[1]] == 0): - min_steps_helper(mat, (pos[0]+1, pos[1]), n, m) - if (pos[0] - 1 >= 0 and mat[pos[0] - 1][pos[1]] == 0): - min_steps_helper(mat, (pos[0]-1, pos[1]), n, m) - if (pos[1] + 1 < m and mat[pos[0]][pos[1] + 1] == 0): - min_steps_helper(mat, (pos[0], pos[1]+1), n, m) - if (pos[1] - 1 >= 0 and mat[pos[0]][pos[1] - 1] == 0): - min_steps_helper(mat, (pos[0], pos[1]-1), n, m) - - print(array(mat)) # Comment out the full line if you dont have numpy + if pos[0] + 1 < n and mat[pos[0] + 1][pos[1]] == 0: + min_steps_helper(mat, (pos[0] + 1, pos[1]), n, m) + if pos[0] - 1 >= 0 and mat[pos[0] - 1][pos[1]] == 0: + min_steps_helper(mat, (pos[0] - 1, pos[1]), n, m) + if pos[1] + 1 < m and mat[pos[0]][pos[1] + 1] == 0: + min_steps_helper(mat, (pos[0], pos[1] + 1), n, m) + if pos[1] - 1 >= 0 and mat[pos[0]][pos[1] - 1] == 0: + min_steps_helper(mat, (pos[0], pos[1] - 1), n, m) + + print(array(mat)) # Comment out the full line if you dont have numpy # mat[end[0]][end[1]] - 1 is returned as initially the value was offsetted by +1 - return (mat[end[0]][end[1]] - 1) + return mat[end[0]][end[1]] - 1 except: return None + # DRIVER CODE -mat = [['f','f','f','f'], - ['t', 't','f', 't'], - ['f','f','f','f'], - ['f','f','f','f']] +mat = [ + ["f", "f", "f", "f"], + ["t", "t", "f", "t"], + ["f", "f", "f", "f"], + ["f", "f", "f", "f"], +] n = len(mat) m = len(mat[0]) start = (3, 0) end = (0, 0) -print(array(mat)) # Comment out the full line if you dont have numpy -print(min_steps(mat, n, m, start, end)) \ No newline at end of file +print(array(mat)) # Comment out the full line if you dont have numpy +print(min_steps(mat, n, m, start, end)) diff --git a/Solutions/230.py b/Solutions/230.py index 8b22c3e..d72a633 100644 --- a/Solutions/230.py +++ b/Solutions/230.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given N identical eggs and access to a building with k floors. @@ -12,20 +12,21 @@ N = 1 k = 5 Output = 5 (we will need to try dropping the egg at every floor, beginning with the first, until we reach the fifth floor) -''' +""" from sys import maxsize def calculate(eggs, floors): - dp_mat = [[0 for _ in range(floors+1)] for _ in range(eggs+1)] - for i in range(floors+1): dp_mat[1][i] = i + dp_mat = [[0 for _ in range(floors + 1)] for _ in range(eggs + 1)] + for i in range(floors + 1): + dp_mat[1][i] = i - for egg in range(2, eggs+1): - for floor in range(1, floors+1): + for egg in range(2, eggs + 1): + for floor in range(1, floors + 1): dp_mat[egg][floor] = maxsize - for i in range(1, floor+1): - temp = 1 + max(dp_mat[egg-1][i-1], dp_mat[egg][floor-i]) + for i in range(1, floor + 1): + temp = 1 + max(dp_mat[egg - 1][i - 1], dp_mat[egg][floor - i]) dp_mat[egg][floor] = min(dp_mat[egg][floor], temp) return dp_mat[eggs][floors] @@ -33,4 +34,4 @@ def calculate(eggs, floors): # DRIVER CODE print(calculate(2, 20)) -print(calculate(3, 15)) \ No newline at end of file +print(calculate(3, 15)) diff --git a/Solutions/231.py b/Solutions/231.py index 8599b4f..9e1de77 100644 --- a/Solutions/231.py +++ b/Solutions/231.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string with repeated characters, rearrange the string so that no two adjacent characters are the same. @@ -11,50 +11,60 @@ Input = "aaab" Output = None -''' +""" + def get_unique_adjacent(string): length = len(string) freq = {} - if (length == 0): return string + if length == 0: + return string # getting the character frequency for i in range(length): - if (string[i] in freq): freq[string[i]] += 1 - else: freq[string[i]] = 1 - + if string[i] in freq: + freq[string[i]] += 1 + else: + freq[string[i]] = 1 + sorted_freq = sorted(freq.items(), key=lambda x: x[1], reverse=True) queue = list(sorted_freq) # checking if a desired string can be formed - if (length % 2 == 0): - if (sorted_freq[0][1] > length // 2): return None + if length % 2 == 0: + if sorted_freq[0][1] > length // 2: + return None else: - if (sorted_freq[0][1] > (length // 2) + 1): return None - + if sorted_freq[0][1] > (length // 2) + 1: + return None + res = "" # creating the required string - while (queue): - if (len(queue) == 1): - if (queue[0][1] == 2): + while queue: + if len(queue) == 1: + if queue[0][1] == 2: res = queue[0][0] + res + queue[0][0] break - elif (queue[0][1] == 1): - if (res[-1] != queue[0][0]): res += queue[0][0] - else: res = queue[0][0] + res + elif queue[0][1] == 1: + if res[-1] != queue[0][0]: + res += queue[0][0] + else: + res = queue[0][0] + res break else: return None - + res += queue[0][0] + queue[1][0] - queue[0] = queue[0][0], queue[0][1]-1 - queue[1] = queue[1][0], queue[1][1]-1 + queue[0] = queue[0][0], queue[0][1] - 1 + queue[1] = queue[1][0], queue[1][1] - 1 - if (len(queue) > 1 and queue[1][1] == 0): queue.pop(1) - if (len(queue) > 0 and queue[0][1] == 0): queue.pop(0) + if len(queue) > 1 and queue[1][1] == 0: + queue.pop(1) + if len(queue) > 0 and queue[0][1] == 0: + queue.pop(0) return res @@ -66,4 +76,4 @@ def get_unique_adjacent(string): # cannot form a word of the desired form print(get_unique_adjacent("aaab")) -print(get_unique_adjacent("aaabbaa")) \ No newline at end of file +print(get_unique_adjacent("aaabbaa")) diff --git a/Solutions/232.py b/Solutions/232.py index a912c48..dbd4600 100644 --- a/Solutions/232.py +++ b/Solutions/232.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement a PrefixMapSum class with the following methods: @@ -10,7 +10,7 @@ >>> assert mapsum.sum("col") == 3 >>> mapsum.insert("column", 2) >>> assert mapsum.sum("col") == 5 -''' +""" from DataStructures.Trie import Trie @@ -21,13 +21,15 @@ def __init__(self): self.hash_map = {} def insert(self, key, value): - if key not in self.hash_map: self.trie.add(key) + if key not in self.hash_map: + self.trie.add(key) self.hash_map[key] = value def sum(self, prefix): words = self.trie.get_suggestions(prefix) result = 0 - for word in words: result += self.hash_map[word] + for word in words: + result += self.hash_map[word] return result @@ -38,4 +40,4 @@ def sum(self, prefix): print(mapsum.sum("col")) mapsum.insert("column", 2) -print(mapsum.sum("col")) \ No newline at end of file +print(mapsum.sum("col")) diff --git a/Solutions/233.py b/Solutions/233.py index 40ec915..f53c45e 100644 --- a/Solutions/233.py +++ b/Solutions/233.py @@ -1,15 +1,17 @@ -''' +""" Problem: Implement the function fib(n), which returns the nth number in the Fibonacci sequence, using only O(1) space. -''' +""" def fib(n): curr, last = 1, 0 - for _ in range(n-1): curr, last = last + curr, curr + for _ in range(n - 1): + curr, last = last + curr, curr return curr # DRIVER CODE -for i in range(1, 11): print(f"Fib {i}:\t{fib(i)}") +for i in range(1, 11): + print(f"Fib {i}:\t{fib(i)}") diff --git a/Solutions/234.py b/Solutions/234.py index d050519..a724509 100644 --- a/Solutions/234.py +++ b/Solutions/234.py @@ -1,30 +1,30 @@ -''' +""" Problem: Recall that the minimum spanning tree is the subset of edges of a tree that connect all its vertices with the smallest possible total edge weight. Given an undirected graph with weighted edges, compute the maximum weight spanning tree. -''' +""" from DataStructures.Graph import Graph_Undirected_Weighted def get_max_span_helper(graph, start, remaining, score): - if (not remaining): + if not remaining: return score scores = [] - + for dest in graph.connections[start]: - if (dest in remaining): + if dest in remaining: rem_cp = set(remaining) rem_cp.remove(dest) new_score = get_max_span_helper( graph, dest, rem_cp, score + graph.connections[start][dest] ) - + scores.append(new_score) - + return max(scores) diff --git a/Solutions/235.py b/Solutions/235.py index 69298bd..0528ba6 100644 --- a/Solutions/235.py +++ b/Solutions/235.py @@ -1,17 +1,17 @@ -''' +""" Problem: Given an array of numbers of length N, find both the minimum and maximum using less than 2 * (N - 2) comparisons. -''' +""" def getMinMax(arr): - if (not arr): + if not arr: return (None, None) length = len(arr) - if (length % 2 == 0): + if length % 2 == 0: max_elem = max(arr[0], arr[1]) min_elem = min(arr[0], arr[1]) start = 2 @@ -23,15 +23,15 @@ def getMinMax(arr): # reducing the number of comparisons by comparing the array elements with # themselves and then comparing the larger with max_elem and smaller with # min_elem (effective comparison = 3 for every 2 elements) - if (arr[i] < arr[i + 1]): + if arr[i] < arr[i + 1]: max_elem = max(max_elem, arr[i + 1]) min_elem = min(min_elem, arr[i]) else: max_elem = max(max_elem, arr[i]) min_elem = min(min_elem, arr[i + 1]) - return (min_elem, max_elem) + return (min_elem, max_elem) print(getMinMax([1000, 11, 445, 1, 330, 3000])) -print(getMinMax([1000, 11, 445, 1, -330])) \ No newline at end of file +print(getMinMax([1000, 11, 445, 1, -330])) diff --git a/Solutions/236.py b/Solutions/236.py index 77ef700..e859d38 100644 --- a/Solutions/236.py +++ b/Solutions/236.py @@ -1,10 +1,11 @@ -''' +""" Problem: You are given a list of N points (x1, y1), (x2, y2), ..., (xN, yN) representing a polygon. You can assume these points are given in order; that is, you can construct the polygon by connecting point 1 to point 2, point 2 to point 3, and so on, finally looping around to connect point N to point 1. Determine if a new point p lies inside this polygon. (If p is on the boundary of the polygon, you should return False). -''' +""" + def is_inside(points, p): # check if the points can form a closed structure @@ -13,11 +14,11 @@ def is_inside(points, p): # Using the following concept: # if a stright line in drawn from the point p to its right (till infinity), the - # drawn line will intersect the lines connecting the points odd number of times - # (if p is enclosed by the points) else the the number of intersections will be + # drawn line will intersect the lines connecting the points odd number of times + # (if p is enclosed by the points) else the the number of intersections will be # even (implying its outside the figure created by the points) - # Details: + # Details: # https://www.geeksforgeeks.org/how-to-check-if-a-given-point-lies-inside-a-polygon/ x, y = p last = points[0] @@ -52,4 +53,4 @@ def is_inside(points, p): # DRIVER CODE print(is_inside([(4, 3), (5, 4), (6, 3), (5, 2)], (3, 3))) -print(is_inside([(4, 3), (5, 4), (6, 3), (5, 2)], (5, 3))) \ No newline at end of file +print(is_inside([(4, 3), (5, 4), (6, 3), (5, 2)], (5, 3))) diff --git a/Solutions/237.py b/Solutions/237.py index c2991ca..fb8bd82 100644 --- a/Solutions/237.py +++ b/Solutions/237.py @@ -1,4 +1,4 @@ -''' +""" Problem: A tree is symmetric if its data and shape remain unchanged when it is reflected about the root node. @@ -9,7 +9,7 @@ / \ 9 9 Given a k-ary tree, determine whether it is symmetric. -''' +""" # Node class to store a k-ary tree class Node: @@ -63,4 +63,4 @@ def is_symmetric(tree): print(is_symmetric(a)) c.val = 4 -print(is_symmetric(a)) \ No newline at end of file +print(is_symmetric(a)) diff --git a/Solutions/238.py b/Solutions/238.py index d04ce24..4b745a3 100644 --- a/Solutions/238.py +++ b/Solutions/238.py @@ -1,4 +1,4 @@ -''' +""" Problem: Blackjack is a two player card game whose rules are as follows: @@ -8,7 +8,7 @@ * Finally, the two compare totals, and the one with the greatest sum not exceeding 21 is the winner. For this problem, cards values are counted as follows: each card between 2 and 10 counts as their face value, face cards count as 10, and aces count as 1. Given perfect knowledge of the sequence of cards in the deck, implement a blackjack solver that maximizes the player's score (that is, wins minus losses). -''' +""" from random import randint @@ -37,7 +37,7 @@ def get_best_score(sequence, player_score=0, dealer_score=0): get_best_score(sequence[1:], player_score, dealer_score + sequence[0]), (player_score, dealer_score), # the player's score has more weightage than the dealer's score - key=lambda x: 1.01 * x[0] + x[1] + key=lambda x: 1.01 * x[0] + x[1], ) @@ -53,4 +53,4 @@ def simulate(n=1000): # DRIVER CODE -print(f"The Player won {simulate():.2f}% of the times") \ No newline at end of file +print(f"The Player won {simulate():.2f}% of the times") diff --git a/Solutions/239.py b/Solutions/239.py index ad649d2..3c66c63 100644 --- a/Solutions/239.py +++ b/Solutions/239.py @@ -1,4 +1,4 @@ -''' +""" Problem: One way to unlock an Android phone is through a pattern of swipes across a 1-9 keypad. @@ -7,7 +7,7 @@ * It must not connect two keys by jumping over a third key, unless that key has already been used. For example, 4 - 2 - 1 - 7 is a valid pattern, whereas 2 - 1 - 7 is not. Find the total number of valid unlock patterns of length N, where 1 <= N <= 9. -''' +""" from copy import deepcopy @@ -26,22 +26,22 @@ def __init__(self): self.edges[7] = {2, 4, 5, 6, 8} self.edges[8] = {1, 4, 3, 5, 6, 7, 9} self.edges[9] = {2, 4, 5, 6, 8} - + def update_connections(self, curr): # function to update the connections - if (2 == curr): + if 2 == curr: self.edges[1].add(3) self.edges[3].add(1) - elif (4 == curr): + elif 4 == curr: self.edges[1].add(7) self.edges[7].add(1) - elif (6 == curr): + elif 6 == curr: self.edges[9].add(3) self.edges[3].add(9) - elif (8 == curr): + elif 8 == curr: self.edges[7].add(9) self.edges[9].add(7) - elif (5 == curr): + elif 5 == curr: self.edges[1].add(9) self.edges[9].add(1) self.edges[7].add(3) @@ -92,4 +92,4 @@ def valid_unlock_patterns_number(): # DRIVER CODE # NOTE: computationally intensive operation as the number of patterns is really high -print(valid_unlock_patterns_number()) \ No newline at end of file +print(valid_unlock_patterns_number()) diff --git a/Solutions/24.py b/Solutions/24.py index 3d00bfa..d387786 100644 --- a/Solutions/24.py +++ b/Solutions/24.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement locking in a binary tree. A binary tree node can be locked or unlocked only if all of its descendants or ancestors are not locked. @@ -10,7 +10,7 @@ You may augment the node to add parent pointers or any other property you would like. You may assume the class is used in a single-threaded program, so there is no need for actual locks or mutexes. Each method should run in O(h), where h is the height of the tree. -''' +""" from DataStructures.Tree import Node, Binary_Tree @@ -18,114 +18,120 @@ class Node_modified(Node): # Initialize function (Automatically called upon creating an object instance) def __init__(self, val): - ''' + """ Node Class for the nodes of a Binary Tree Functions: to_str: __str__ helper function height_helper: helper function to calculate the height of a Binary Tree insert_helper: helper function to add node in a Binary Search Tree - ''' + """ Node.__init__(self, val) self.locked = False self.parent = None - + # String function (Automatically called upon converting to string, generally used when printing) def __str__(self): return f"Value: {self.val}\nStatus: {'Locked' if self.locked else 'Unlocked'}" - + # FUNCTION TO PERFORM THE OPERATION (is locked) def is_locked(self): return self.locked - + # Helper function to check if any of the descendant is not locked def check_descendant_helper(self): # If an unlocked node is found, True is returned - if (not self.locked): + if not self.locked: return True - + # If the immediate children doesn't contain any unlocked node, the function is called recursively to traverse the subtrees else: - if (self.left): + if self.left: left = self.left.check_descendant_helper() else: left = False - - if (self.right and not self.left): + + if self.right and not self.left: right = self.right.check_descendant_helper() else: right = False - + # If any of the subtree contain an unlocked node, the value becomes True (left or right) - return (left or right) - + return left or right + # FUNCTION TO PERFORM THE OPERATION (lock) def lock(self): flag = False node = self # Searching for an unlocked parent node - while (node.parent): - if (not node.is_locked()): + while node.parent: + if not node.is_locked(): flag = True break node = node.parent # If no parent is unlocked, then an unlocked child node is searched else: - if ((self.left and self.left.check_descendant_helper()) or (self.right and self.right.check_descendant_helper())): + if (self.left and self.left.check_descendant_helper()) or ( + self.right and self.right.check_descendant_helper() + ): flag = True - + # If any unlocked node is found, after performing the action (swapping the locked variable) True is returned - if (flag): + if flag: self.locked = True return True return False - + # FUNCTION TO PERFORM THE OPERATION (unlock) def unlock(self): flag = False node = self # Searching for an unlocked parent node - while (node.parent): - if (not node.is_locked()): + while node.parent: + if not node.is_locked(): flag = True break node = node.parent # If no parent is unlocked, then an unlocked child node is searched else: - if ((self.left and self.left.check_descendant_helper()) or (self.right and self.right.check_descendant_helper())): + if (self.left and self.left.check_descendant_helper()) or ( + self.right and self.right.check_descendant_helper() + ): flag = True - + # If any unlocked node is found, after performing the action (swapping the locked variable) True is returned - if (flag): + if flag: self.locked = False return True - + return False - + # Helper function to print all nodes (Recursively - Inplace) def to_str(self): - if (self.left): + if self.left: self.left.to_str() - - print(f'\n{self}\n') - if (self.right): + print(f"\n{self}\n") + + if self.right: self.right.to_str() + # Modified Binary Tree Class -class Binary_Tree_modified(): +class Binary_Tree_modified: # String function (Automatically called upon converting to string, generally used when printing) def __init__(self): self.root = None - + # Helper function to print all nodes (Uses helper function in Node_modified) def to_str(self): self.root.to_str() + # DRIVER CODE tree = Binary_Tree_modified() tree.root = Node_modified(5) @@ -143,4 +149,4 @@ def to_str(self): print(tree.root.lock()) print(tree.root.left.unlock()) -tree.to_str() \ No newline at end of file +tree.to_str() diff --git a/Solutions/240.py b/Solutions/240.py index 2dafd35..9f11db9 100644 --- a/Solutions/240.py +++ b/Solutions/240.py @@ -1,13 +1,14 @@ -''' +""" Problem: There are N couples sitting in a row of length 2 * N. They are currently ordered randomly, but would like to rearrange themselves so that each couple's partners can sit side by side. What is the minimum number of swaps necessary for this to happen? -''' +""" # The range of the swaps is [0, ceil(N / 2)] + def get_desired_index(curr_index): if curr_index % 2 == 0: return curr_index + 1 @@ -37,4 +38,4 @@ def couple_pairing(array): # DRIVER CODE print(couple_pairing([2, 1, 2, 3, 1, 3])) -print(couple_pairing([3, 2, 1, 1, 2, 3])) \ No newline at end of file +print(couple_pairing([3, 2, 1, 1, 2, 3])) diff --git a/Solutions/241.py b/Solutions/241.py index 3fc88b2..ef703a2 100644 --- a/Solutions/241.py +++ b/Solutions/241.py @@ -1,4 +1,4 @@ -''' +""" Problem: In academia, the h-index is a metric used to calculate the impact of a researcher's papers. @@ -12,7 +12,8 @@ N = 5 citations = [4, 3, 0, 1, 5] Output = 3 (since the researcher has 3 papers with at least 3 citations) -''' +""" + def get_h_index(citations): citations.sort(reverse=True) @@ -26,4 +27,4 @@ def get_h_index(citations): # DRIVER CODE print(get_h_index([4, 3, 0, 1, 5])) print(get_h_index([4, 1, 0, 1, 1])) -print(get_h_index([4, 4, 4, 5, 4])) \ No newline at end of file +print(get_h_index([4, 4, 4, 5, 4])) diff --git a/Solutions/242.py b/Solutions/242.py index 9c37abb..9161d6e 100644 --- a/Solutions/242.py +++ b/Solutions/242.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an array of length 24, where each element represents the number of new subscribers during the corresponding hour. @@ -6,15 +6,16 @@ * update(hour: int, value: int): Increment the element at index hour by value. * query(start: int, end: int): Retrieve the number of subscribers that have signed up between start and end (inclusive). You can assume that all values get cleared at the end of the day, and that you will not be asked for start and end values that wrap around midnight. -''' +""" + class Hourly_Subscribers: def __init__(self): self.sub_count = [0 for _ in range(24)] - + def update(self, hour, value): self.sub_count[hour - 1] += value - + def query(self, start, end): return sum(self.sub_count[start : end + 1]) @@ -29,4 +30,4 @@ def query(self, start, end): hs.update(2, 10) -print(hs.query(1, 7)) \ No newline at end of file +print(hs.query(1, 7)) diff --git a/Solutions/243.py b/Solutions/243.py index 399d211..ee6cfb3 100644 --- a/Solutions/243.py +++ b/Solutions/243.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of numbers N and an integer k, your task is to split N into k partitions such that the maximum sum of any partition is minimized. @@ -9,7 +9,7 @@ N = [5, 1, 2, 7, 3, 4] k = 3 Output = 8 (since the optimal partition is [5, 1, 2], [7], [3, 4]) -''' +""" from sys import maxsize @@ -38,4 +38,4 @@ def minimize_partition_sum(arr, k): # DRIVER CODE -print(minimize_partition_sum([5, 1, 2, 7, 3, 4], 3)) \ No newline at end of file +print(minimize_partition_sum([5, 1, 2, 7, 3, 4], 3)) diff --git a/Solutions/244.py b/Solutions/244.py index 182ed04..3732c18 100644 --- a/Solutions/244.py +++ b/Solutions/244.py @@ -1,4 +1,4 @@ -''' +""" Problem: The Sieve of Eratosthenes is an algorithm used to generate all prime numbers smaller than N. @@ -8,7 +8,8 @@ Implement this algorithm. Bonus: Create a generator that produces primes indefinitely (that is, without taking N as an input). -''' +""" + def SoE(sieve=[]): # if an sieve is passed, its doubled in size to generate a larger sieve diff --git a/Solutions/245.py b/Solutions/245.py index f86a677..cdf2370 100644 --- a/Solutions/245.py +++ b/Solutions/245.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an array of integers, where each element represents the maximum number of steps that can be jumped going forward from that element. @@ -8,7 +8,7 @@ Input = [6, 2, 4, 0, 5, 1, 1, 4, 2, 9] Output = 2 (as the optimal solution involves jumping from 6 to 5, and then from 5 to 9) -''' +""" from sys import maxsize @@ -17,14 +17,14 @@ def get_min_jumps(arr): length = len(arr) # using dynamic programming to reduce O(n ^ n) problem to O(n ^ 2) dp = [0 for _ in range(length)] - for i in range(length-2, -1, -1): + for i in range(length - 2, -1, -1): # updating the minimum hops for each position if arr[i]: - dp[i] = min(dp[i+1 : i+arr[i]+1]) + 1 + dp[i] = min(dp[i + 1 : i + arr[i] + 1]) + 1 else: dp[i] = maxsize return dp[0] # DRIVER CODE -print(get_min_jumps([6, 2, 4, 0, 5, 1, 1, 4, 2, 9])) \ No newline at end of file +print(get_min_jumps([6, 2, 4, 0, 5, 1, 1, 4, 2, 9])) diff --git a/Solutions/246.py b/Solutions/246.py index 4eb88e7..162ab81 100644 --- a/Solutions/246.py +++ b/Solutions/246.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of words, determine whether the words can be chained to form a circle. @@ -8,7 +8,8 @@ Input = ['chair', 'height', 'racket', 'touch', 'tunic'] Output = True (chair -> racket -> touch -> height -> tunic -> chair) -''' +""" + def check_circle_formation_helper(word_list, start, end, curr, start_word, seen): # checking if all words have been used @@ -24,9 +25,11 @@ def check_circle_formation_helper(word_list, start, end, curr, start_word, seen) seen_copy = seen.copy() seen_copy.add(word) # checking if a cycle can be formed - if check_circle_formation_helper(word_list, start, end, word, start_word, seen_copy): + if check_circle_formation_helper( + word_list, start, end, word, start_word, seen_copy + ): return True - except KeyError: # incase the current word's last character isn't present in start + except KeyError: # incase the current word's last character isn't present in start pass return False @@ -44,13 +47,23 @@ def check_circle_formation(word_list): end[word[-1]].add(word) # starting with all words and checking if a circle can be formed for word in word_list: - if check_circle_formation_helper(word_list, start, end, word, word, set([word])): + if check_circle_formation_helper( + word_list, start, end, word, word, set([word]) + ): return True return False # DRIVER CODE -print(check_circle_formation(['chair', 'height', 'racket', 'touch', 'tunic'])) # chair, racket, touch, height, tunic, chair -print(check_circle_formation(['height', 'racket', 'touch', 'tunic', 'car'])) # racket, touch, height, tunic, car, racket -print(check_circle_formation(['height', 'racket', 'touch', 'tunic'])) # racket, touch, height, tunic (but no looping) -print(check_circle_formation(['height', 'racket', 'touch', 'tunic', 'cat'])) # no looping \ No newline at end of file +print( + check_circle_formation(["chair", "height", "racket", "touch", "tunic"]) +) # chair, racket, touch, height, tunic, chair +print( + check_circle_formation(["height", "racket", "touch", "tunic", "car"]) +) # racket, touch, height, tunic, car, racket +print( + check_circle_formation(["height", "racket", "touch", "tunic"]) +) # racket, touch, height, tunic (but no looping) +print( + check_circle_formation(["height", "racket", "touch", "tunic", "cat"]) +) # no looping diff --git a/Solutions/247.py b/Solutions/247.py index 676b1dd..9fbe3d4 100644 --- a/Solutions/247.py +++ b/Solutions/247.py @@ -1,9 +1,9 @@ -''' +""" Problem: Given a binary tree, determine whether or not it is height-balanced. A height-balanced binary tree can be defined as one in which the heights of the two subtrees of any node never differ by more than one. -''' +""" from DataStructures.Tree import Node, Binary_Tree @@ -31,8 +31,8 @@ def check_balance(self): # adding required methods to the classes -setattr(Node, 'height_helper', height_helper) -setattr(Binary_Tree, 'check_balance', check_balance) +setattr(Node, "height_helper", height_helper) +setattr(Binary_Tree, "check_balance", check_balance) # DRIVER CODE diff --git a/Solutions/248.py b/Solutions/248.py index 90f9148..5cb9662 100644 --- a/Solutions/248.py +++ b/Solutions/248.py @@ -1,12 +1,12 @@ -''' +""" Problem: Find the maximum of two numbers without using any if-else statements, branching, or direct comparisons. -''' +""" # max using bit-wise operations def get_max(num1, num2): - return num1 ^ ((num1 ^ num2) & -(num1 < num2)) + return num1 ^ ((num1 ^ num2) & -(num1 < num2)) # DRIVER CODE diff --git a/Solutions/249.py b/Solutions/249.py index 0fbc296..1b28407 100644 --- a/Solutions/249.py +++ b/Solutions/249.py @@ -1,8 +1,8 @@ -''' +""" Problem: Given an array of integers, find the maximum XOR of any two elements. -''' +""" from sys import maxsize @@ -10,10 +10,10 @@ def get_max_xor(arr): max_xor = -maxsize for index, elem1 in enumerate(arr): - for elem2 in arr[index + 1:]: + for elem2 in arr[index + 1 :]: max_xor = max(max_xor, elem1 ^ elem2) return max_xor # DRIVER CODE -print(get_max_xor([1, 2, 3, 4])) \ No newline at end of file +print(get_max_xor([1, 2, 3, 4])) diff --git a/Solutions/25.py b/Solutions/25.py index d6a8044..08d5666 100644 --- a/Solutions/25.py +++ b/Solutions/25.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement regular expression matching with the following special characters: @@ -9,7 +9,7 @@ Example: Input = "ra.", "ray" Output = True -''' +""" # FUNCTION TO PERFORM THE OPERATION def regex(expression, string): @@ -28,15 +28,15 @@ def regex(expression, string): # Looping over the expression for i in range(len_ex): # If no "*" has been encountered - if (not flag): + if not flag: # if the expression and the string have the same characters at the position under consideration, the value of pos is incremented - if (expression[i] == string[pos]): + if expression[i] == string[pos]: pos += 1 # if the expression has a ".", pos is incremented - elif (expression[i] == '.'): + elif expression[i] == ".": pos += 1 # if the expression has a "*", flag is set to True - elif (expression[i] == '*'): + elif expression[i] == "*": flag = True # if mismatch occours, False is returned else: @@ -48,21 +48,22 @@ def regex(expression, string): temp = expression[i] # Incrementing pos till a different character is encountered - while (string[pos] == temp): + while string[pos] == temp: pos += 1 - + # Resetting flag to ensure the control doesn't enter this segment again till another "*" is encounterd flag = False - + # Returning False incase of IndexError except IndexError: return False return True + # DRIVER CODE print(regex("r.y", "ray")) print(regex("ra.", "ray")) print(regex("r.*", "rabcdefgh")) print(regex(".*at", "chat")) -print(regex(".*at", "chats")) \ No newline at end of file +print(regex(".*at", "chats")) diff --git a/Solutions/250.py b/Solutions/250.py index e718117..becbd57 100644 --- a/Solutions/250.py +++ b/Solutions/250.py @@ -1,4 +1,4 @@ -''' +""" Problem: A cryptarithmetic puzzle is a mathematical game where the digits of some numbers are @@ -11,7 +11,8 @@ may have the solution: {'S': 9, 'E': 5, 'N': 6, 'D': 7, 'M': 1, 'O': 0, 'R': 8, 'Y': 2} Given a three-word puzzle like the one above, create an algorithm that finds a solution -''' +""" + def get_num_from_string(char_map, string): # function to generate the value of a number from the charater map and string @@ -55,7 +56,8 @@ def assign_letters(chars_left, nums_left, restrictions, char_map={}): chars_left - set([curr_char]), nums_left - set([num]), restrictions, - char_map_cp) + char_map_cp, + ) char_maps.extend(child_char_maps) return char_maps @@ -78,4 +80,4 @@ def decode(exp1, exp2, res): # DRIVER CODE -print(decode("SEND", "MORE", "MONEY")) \ No newline at end of file +print(decode("SEND", "MORE", "MONEY")) diff --git a/Solutions/251.py b/Solutions/251.py index 9a25adc..e72f59d 100644 --- a/Solutions/251.py +++ b/Solutions/251.py @@ -1,9 +1,9 @@ -''' +""" Problem: Given an array of a million integers between zero and a billion, out of order, how can you efficiently sort it? Assume that you cannot store an array of a billion elements in memory. -''' +""" from random import randint @@ -33,7 +33,7 @@ def countingSort(arr, exp, n): arr[i] = output[i] -# Method to do Radix Sort +# Method to do Radix Sort def radixSort(arr): length = len(arr) # find the number digits in the largest number (generalized for any array) diff --git a/Solutions/252.py b/Solutions/252.py index 45a3ecd..c23a702 100644 --- a/Solutions/252.py +++ b/Solutions/252.py @@ -1,10 +1,10 @@ -''' +""" Problem: The ancient Egyptians used to express fractions as a sum of several terms where each numerator is one. Create an algorithm to turn an ordinary fraction a / b, where a < b, into an Egyptian fraction. For example, 4 / 13 can be represented as 1 / 4 + 1 / 18 + 1 / 468. -''' +""" from fractions import Fraction from math import ceil diff --git a/Solutions/253.py b/Solutions/253.py index 7c84edc..c3d15fc 100644 --- a/Solutions/253.py +++ b/Solutions/253.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string and a number of lines k, print the string in zigzag form. In zigzag, characters are printed out diagonally from top left to bottom right until reaching the kth line, then back up to top right, and so on. @@ -9,7 +9,7 @@ h s z a i i i z s g -''' +""" def clamp(num, min_value, max_value): diff --git a/Solutions/254.py b/Solutions/254.py index 615fdff..8dd1b64 100644 --- a/Solutions/254.py +++ b/Solutions/254.py @@ -1,4 +1,4 @@ -''' +""" Probelm: Recall that a full binary tree is one in which each node is either a leaf node, or has two children. Given a binary tree, convert it to a full one by removing nodes with only one child. @@ -17,7 +17,7 @@ f e / \ g h -''' +""" from DataStructures.Tree import Node, Binary_Tree @@ -47,23 +47,23 @@ def create_full_bin_tree(self): self.root.create_full_bin_tree_helper() -setattr(Node, 'create_full_bin_tree_helper', create_full_bin_tree_helper) -setattr(Binary_Tree, 'create_full_bin_tree', create_full_bin_tree) +setattr(Node, "create_full_bin_tree_helper", create_full_bin_tree_helper) +setattr(Binary_Tree, "create_full_bin_tree", create_full_bin_tree) # DRIVER CODE tree = Binary_Tree() -tree.root = Node('a') -tree.root.left = Node('b') -tree.root.right = Node('c') +tree.root = Node("a") +tree.root.left = Node("b") +tree.root.right = Node("c") -tree.root.left.left = Node('d') -tree.root.left.left.right = Node('f') +tree.root.left.left = Node("d") +tree.root.left.left.right = Node("f") -tree.root.right.right = Node('e') -tree.root.right.right.left = Node('g') -tree.root.right.right.right = Node('h') +tree.root.right.right = Node("e") +tree.root.right.right.left = Node("g") +tree.root.right.right.right = Node("h") print(tree) diff --git a/Solutions/255.py b/Solutions/255.py index 02d727e..be3726b 100644 --- a/Solutions/255.py +++ b/Solutions/255.py @@ -1,4 +1,4 @@ -''' +""" Problem: The transitive closure of a graph is a measure of which vertices are reachable from other vertices. It can be represented as a matrix M, where M[i][j] == 1 if there is a path between vertices i and j, and otherwise 0. @@ -18,7 +18,8 @@ [0, 0, 1, 0] [0, 0, 0, 1] Given a graph, find its transitive closure. -''' +""" + def get_transitive_helper(origin, curr_node, graph, transitive_matrix, visited): # helper function to generate the transitive matrix using dfs @@ -39,12 +40,7 @@ def get_transitive(graph): # DRIVER CODE -graph = [ - [0, 1, 3], - [1, 2], - [2], - [3] -] +graph = [[0, 1, 3], [1, 2], [2], [3]] for row in get_transitive(graph): print(*row) diff --git a/Solutions/256.py b/Solutions/256.py index 356477f..3c32aa3 100644 --- a/Solutions/256.py +++ b/Solutions/256.py @@ -1,8 +1,8 @@ -''' +""" Problem: Given a linked list, rearrange the node values such that they appear in alternating low -> high -> low -> high ... form. For example, given 1 -> 2 -> 3 -> 4 -> 5, you should return 1 -> 3 -> 2 -> 5 -> 4. -''' +""" from DataStructures.LinkedList import Node, Linked_list @@ -22,7 +22,7 @@ def rearrange(self): # adding the rearrange method to the class -setattr(Linked_list, 'rearrange', rearrange) +setattr(Linked_list, "rearrange", rearrange) # DRIVER CODE diff --git a/Solutions/257.py b/Solutions/257.py index b4a1892..b507c5f 100644 --- a/Solutions/257.py +++ b/Solutions/257.py @@ -1,8 +1,8 @@ -''' +""" Problem: Given an array of integers out of order, determine the bounds of the smallest window that must be sorted in order for the entire array to be sorted. For example, given [3, 7, 5, 6, 9], you should return (1, 3). -''' +""" def get_sort_range(arr): @@ -27,4 +27,4 @@ def get_sort_range(arr): # DRIVER CODE print(get_sort_range([3, 5, 6, 7, 9])) print(get_sort_range([3, 7, 5, 6, 9])) -print(get_sort_range([5, 4, 3, 2, 1])) \ No newline at end of file +print(get_sort_range([5, 4, 3, 2, 1])) diff --git a/Solutions/258.py b/Solutions/258.py index 0bbf5e7..029db37 100644 --- a/Solutions/258.py +++ b/Solutions/258.py @@ -1,4 +1,4 @@ -''' +""" Problem: In Ancient Greece, it was common to write text with the first line going left to right, the second line going right to left, and continuing to go back and forth. This style was called "boustrophedon". @@ -14,7 +14,7 @@ 4 5 6 7 You should return [1, 3, 2, 4, 5, 6, 7]. -''' +""" from DataStructures.Tree import Node, Binary_Tree @@ -46,8 +46,8 @@ def get_boustrophedon(self): return result -setattr(Node, 'get_boustrophedon_helper', get_boustrophedon_helper) -setattr(Binary_Tree, 'get_boustrophedon', get_boustrophedon) +setattr(Node, "get_boustrophedon_helper", get_boustrophedon_helper) +setattr(Binary_Tree, "get_boustrophedon", get_boustrophedon) # DRIVER CODE diff --git a/Solutions/259.py b/Solutions/259.py index b6518a7..c8f1818 100644 --- a/Solutions/259.py +++ b/Solutions/259.py @@ -1,4 +1,4 @@ -''' +""" Problem: Ghost is a two-person word game where players alternate appending letters to a word. The first person who spells out a word, or creates a prefix for which there is no possible continuation, loses. Here is a sample game: @@ -11,7 +11,8 @@ Given a dictionary of words, determine the letters the first player should start with, such that with optimal play they cannot lose. For example, if the dictionary is ["cat", "calf", "dog", "bear"], the only winning start letter would be b. -''' +""" + def get_winning_letters(words): # creating a map of starting characters to the words @@ -20,7 +21,7 @@ def get_winning_letters(words): if word[0] not in starting_char_freq: starting_char_freq[word[0]] = [] starting_char_freq[word[0]].append(word) - # getting the winning start characters + # getting the winning start characters # requirements: only 1 word starts with the character & its length is even winning_start_letters = set() for starting_char in starting_char_freq: @@ -32,4 +33,4 @@ def get_winning_letters(words): # DRIVER CODE print(get_winning_letters(["cat", "calf", "dog", "bear"])) -print(get_winning_letters(["cat", "something", "hi", "calf", "dog", "bear"])) \ No newline at end of file +print(get_winning_letters(["cat", "something", "hi", "calf", "dog", "bear"])) diff --git a/Solutions/26.py b/Solutions/26.py index 197943d..eae8b05 100644 --- a/Solutions/26.py +++ b/Solutions/26.py @@ -1,11 +1,11 @@ -''' +""" Problem: Given a singly linked list and an integer k, remove the kth last element from the list. k is guaranteed to be smaller than the length of the list. The list is very long, so making more than one pass is prohibitively expensive. Do this in constant space and in one pass. -''' +""" # Importing from the local module from DataStructures.LinkedList import Node, Linked_list @@ -19,15 +19,15 @@ def del_LL_k(LL, k): iterations = 0 # Looping over till the end of the linked list - while (ptr1.next): + while ptr1.next: ptr1 = ptr1.next iterations += 1 # If at least k iterations has been made, ptr2 is moved to the next node in each iteration # So ptr2 trails ptr1 by k nodes - if (iterations >= k): + if iterations >= k: ptr2 = ptr2.next - + # Storing the reference (as it needs to be deleted after the reference is removed) temp = ptr2.next @@ -38,6 +38,7 @@ def del_LL_k(LL, k): # Deleting using the stored refernce del temp + # DRIVER CODE LL = Linked_list() LL.add(5) @@ -53,4 +54,4 @@ def del_LL_k(LL, k): del_LL_k(LL, 5) -print(LL) \ No newline at end of file +print(LL) diff --git a/Solutions/260.py b/Solutions/260.py index 617ff53..580e3ab 100644 --- a/Solutions/260.py +++ b/Solutions/260.py @@ -1,8 +1,9 @@ -''' +""" Problem: The sequence [0, 1, ..., N] has been jumbled, and the only clue you have for its order is an array representing whether each number is larger or smaller than the last. Given this information, reconstruct an array that is consistent with it. For example, given [None, +, +, -, +], you could return [1, 2, 3, 0, 4]. -''' +""" + def get_sequence(relative_arr): # getting the number of '+' and generating the first number @@ -14,7 +15,7 @@ def get_sequence(relative_arr): # generating the result array result = [first_num] for elem in relative_arr[1:]: - if (elem == "+"): + if elem == "+": result.append(larger_num) larger_num += 1 else: @@ -24,4 +25,4 @@ def get_sequence(relative_arr): # DRIVER CODE -print(get_sequence([None, "+", "+", "-", "+"])) \ No newline at end of file +print(get_sequence([None, "+", "+", "-", "+"])) diff --git a/Solutions/261.py b/Solutions/261.py index ec517a8..db263d0 100644 --- a/Solutions/261.py +++ b/Solutions/261.py @@ -1,4 +1,4 @@ -''' +""" Problem: Huffman coding is a method of encoding characters based on their frequency. Each letter @@ -21,7 +21,7 @@ Given a dictionary of character frequencies, build a Huffman tree, and use it to determine a mapping between characters and their encoded binary strings. -''' +""" from typing import Dict @@ -29,15 +29,15 @@ from DataStructures.Tree import Node -def huffman_code_tree(node: Node, - left: bool = True, - binString: str = '') -> Dict[str, str]: +def huffman_code_tree( + node: Node, left: bool = True, binString: str = "" +) -> Dict[str, str]: # function implementing huffman coding if type(node) is str: return {node: binString} d = dict() - d.update(huffman_code_tree(node.left, True, binString + '0')) - d.update(huffman_code_tree(node.right, False, binString + '1')) + d.update(huffman_code_tree(node.left, True, binString + "0")) + d.update(huffman_code_tree(node.right, False, binString + "1")) return d @@ -56,4 +56,4 @@ def get_huffman_code(char_freq: Dict[str, int]) -> Dict[str, str]: if __name__ == "__main__": - print(get_huffman_code({'c': 1, 'a': 2, 't': 2, 's': 1})) + print(get_huffman_code({"c": 1, "a": 2, "t": 2, "s": 1})) diff --git a/Solutions/262.py b/Solutions/262.py index 097272c..9e325aa 100644 --- a/Solutions/262.py +++ b/Solutions/262.py @@ -1,9 +1,9 @@ -''' +""" Problem: A bridge in a connected (undirected) graph is an edge that, if removed, causes the graph to become disconnected. Find all the bridges in a graph. -''' +""" from sys import maxsize from typing import Dict, List, Optional, Tuple @@ -12,17 +12,19 @@ from DataStructures.Graph import GraphUndirectedUnweighted -def get_bridges_helper(self, - node: int, - visited: set, - parent: Dict[int, Optional[int]], - low: Dict[int, int], - disc: Dict[int, int], - bridges: List[Tuple[int, int]]) -> None: +def get_bridges_helper( + self, + node: int, + visited: set, + parent: Dict[int, Optional[int]], + low: Dict[int, int], + disc: Dict[int, int], + bridges: List[Tuple[int, int]], +) -> None: # DFS based helper function to find all bridges visited.add(node) - disc[node] = self.time - low[node] = self.time + disc[node] = self.time + low[node] = self.time self.time += 1 for neighbour in self.connections[node]: if neighbour not in visited: @@ -40,7 +42,7 @@ def get_bridges_helper(self, low[node] = min(low[node], disc[neighbour]) -def get_bridges(self) -> List[Tuple[int, int]]: +def get_bridges(self) -> List[Tuple[int, int]]: # function to get all the bridges in a graph visited = set() disc = {node: maxsize for node in self.connections} @@ -55,36 +57,36 @@ def get_bridges(self) -> List[Tuple[int, int]]: # adding the required methods and attributes to the graph class -setattr(GraphUndirectedUnweighted, 'get_bridges_helper', get_bridges_helper) -setattr(GraphUndirectedUnweighted, 'get_bridges', get_bridges) -setattr(GraphUndirectedUnweighted, 'time', 0) +setattr(GraphUndirectedUnweighted, "get_bridges_helper", get_bridges_helper) +setattr(GraphUndirectedUnweighted, "get_bridges", get_bridges) +setattr(GraphUndirectedUnweighted, "time", 0) if __name__ == "__main__": g1 = GraphUndirectedUnweighted() - g1.add_edge(1, 0) - g1.add_edge(0, 2) - g1.add_edge(2, 1) - g1.add_edge(0, 3) + g1.add_edge(1, 0) + g1.add_edge(0, 2) + g1.add_edge(2, 1) + g1.add_edge(0, 3) g1.add_edge(3, 4) print("Bridges in first graph:") print(*g1.get_bridges()) - - g2 = GraphUndirectedUnweighted() - g2.add_edge(0, 1) - g2.add_edge(1, 2) - g2.add_edge(2, 3) + + g2 = GraphUndirectedUnweighted() + g2.add_edge(0, 1) + g2.add_edge(1, 2) + g2.add_edge(2, 3) print("\nBridges in second graph:") print(*g2.get_bridges()) - - g3 = GraphUndirectedUnweighted () - g3.add_edge(0, 1) - g3.add_edge(1, 2) - g3.add_edge(2, 0) - g3.add_edge(1, 3) - g3.add_edge(1, 4) - g3.add_edge(1, 6) - g3.add_edge(3, 5) - g3.add_edge(4, 5) + + g3 = GraphUndirectedUnweighted() + g3.add_edge(0, 1) + g3.add_edge(1, 2) + g3.add_edge(2, 0) + g3.add_edge(1, 3) + g3.add_edge(1, 4) + g3.add_edge(1, 6) + g3.add_edge(3, 5) + g3.add_edge(4, 5) print("\nBridges in third graph:") print(*g3.get_bridges()) diff --git a/Solutions/27.py b/Solutions/27.py index 38ec52e..42e44e7 100644 --- a/Solutions/27.py +++ b/Solutions/27.py @@ -1,12 +1,14 @@ -''' +""" Problem: Given a string of round, curly, and square open and closing brackets, return whether the brackets are balanced (well-formed). -''' +""" # FUNCTION TO PERFORM THE OPERATION -def check(string, inp_dict={"{": "}", "[": "]", "(": ")"}): # By default round, curly, and square are considered, but other combinations can be used too - open_set = set(inp_dict.keys()) # Creating a set of opening brackets +def check( + string, inp_dict={"{": "}", "[": "]", "(": ")"} +): # By default round, curly, and square are considered, but other combinations can be used too + open_set = set(inp_dict.keys()) # Creating a set of opening brackets # Declaring the stack stack = [] @@ -15,24 +17,25 @@ def check(string, inp_dict={"{": "}", "[": "]", "(": ")"}): # By default round, try: for i in string: # If the charcter is an opening bracket and the stack is empty its added to the stack - if (i in open_set): + if i in open_set: stack.append(i) # If its a closing bracket and the stack top contains the corresponding opening bracket, the opening bracket is pop-ed - elif (inp_dict[stack[-1]] == i): + elif inp_dict[stack[-1]] == i: stack.pop() # Otherwise it isn't balanced else: return False except: return False - + # If the stack is empty, the number of opening and closing brackets are equal and balanced - if (stack == []): + if stack == []: return True else: return False + # DRIVER CODE print(check("([])[]({})")) print(check("([)]")) -print(check("((()")) \ No newline at end of file +print(check("((()")) diff --git a/Solutions/28.py b/Solutions/28.py index db3c97d..0eec460 100644 --- a/Solutions/28.py +++ b/Solutions/28.py @@ -1,4 +1,4 @@ -''' +""" Problem: Write an algorithm to justify text. @@ -14,7 +14,7 @@ Output = ["the quick brown", # 1 extra space on the left "fox jumps over", # 2 extra spaces distributed evenly "the lazy dog"] # 4 extra spaces distributed evenly -''' +""" # FUNCTION TO PERFORM THE OPERATION def justify(word_list, k): @@ -29,89 +29,92 @@ def justify(word_list, k): # Looping over the list of words for i in word_list: # if no words have been added to temp - if (temp == []): + if temp == []: # if the word is longer than k, no justification is possible - if (len(i) > k): + if len(i) > k: return [None] # else the word is added to temp and length updated else: temp.append(i) length = len(i) - + # if after the adding the current word, the length is within the limit, its added to temp and length updated - elif (len(i) + length + 1 <= k): + elif len(i) + length + 1 <= k: temp.append(i) length += len(i) + 1 - + # if after the adding the current word, the length oversteps the limit - elif (len(i) + length + 1 > k): + elif len(i) + length + 1 > k: # if the word is longer than k, no justification is possible - if (len(i)+1 > k): + if len(i) + 1 > k: return [None] # Adding the final result to res else: # Extra spaces left extra = k - length - + # if only 1 word is present, extra padding is added to the right - if (len(temp) == 1): + if len(temp) == 1: res.append(temp[0] + " " * extra) # if the space can be equally distributed, it is done so - elif (extra % (len(temp)-1) == 0): - res.append((" " * (extra // (len(temp)-1) + 1)).join(temp)) + elif extra % (len(temp) - 1) == 0: + res.append((" " * (extra // (len(temp) - 1) + 1)).join(temp)) # if the space cannot be equally distributed, extra spaces are added betweens the words, starting from the left else: - extra_extra = extra % (len(temp)-1) - regular = extra // (len(temp)-1) + 1 + extra_extra = extra % (len(temp) - 1) + regular = extra // (len(temp) - 1) + 1 - temp_str = '' + temp_str = "" for i in temp: - temp_str += i + ' ' * regular + temp_str += i + " " * regular - if (extra_extra): - temp_str += ' ' + if extra_extra: + temp_str += " " extra_extra -= 1 - + res.append(temp_str.rstrip()) # updating temp and length temp = [i] length = len(i) - + # operation after the iteration is complete (to add the last set of word(s)) - if (temp != []): + if temp != []: # Extra spaces left extra = k - length - - if (len(temp) == 1): + + if len(temp) == 1: res.append(temp[0] + " " * extra) # if the space can be equally distributed, it is done so - elif (extra % (len(temp)-1) == 0): - res.append((" " * (extra // (len(temp)-1) + 1)).join(temp)) + elif extra % (len(temp) - 1) == 0: + res.append((" " * (extra // (len(temp) - 1) + 1)).join(temp)) # if the space cannot be equally distributed, extra spaces are added betweens the words, starting from the left else: - extra_extra = extra % (len(temp)-1) - regular = extra // (len(temp)-1) + 1 + extra_extra = extra % (len(temp) - 1) + regular = extra // (len(temp) - 1) + 1 - temp_str = '' + temp_str = "" for i in temp: - temp_str += i + ' ' * regular + temp_str += i + " " * regular - if (extra_extra): - temp_str += ' ' + if extra_extra: + temp_str += " " extra_extra -= 1 - + res.append(temp_str.rstrip()) - + return res + # DRIVER CODE -for i in justify(["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog", "Done"], 16): +for i in justify( + ["the", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog", "Done"], 16 +): # NOTE: Using the "'"s is not important, used it to denote thestart and end of the string (helpful in case of 1 word in 1 line) - print("'" + i + "'") \ No newline at end of file + print("'" + i + "'") diff --git a/Solutions/29.py b/Solutions/29.py index e506aca..3672d3c 100644 --- a/Solutions/29.py +++ b/Solutions/29.py @@ -1,4 +1,4 @@ -''' +""" Problem: Run-length encoding is a fast and simple method of encoding strings. @@ -16,7 +16,7 @@ DECODE: Input = "4A3B2C1D2A" Output = "AAAABBBCCDAA" -''' +""" # FUNCTION TO PERFORM THE OPERATION (Encode) def encode(string): @@ -31,14 +31,14 @@ def encode(string): # Looping over the string for i in string: # if the current charcter differs from the character in temp, count and temp is added to the answer - if (i != temp): + if i != temp: ans += str(count) + temp temp = i count = 1 # if the current charcter is same as temp, count is incremented else: count += 1 - + # Adding the last character and count ans += str(count) + temp temp = i @@ -46,6 +46,7 @@ def encode(string): return ans + # FUNCTION TO PERFORM THE OPERATION (Decode) def decode(string): # Declaring necessary variables @@ -57,15 +58,16 @@ def decode(string): # Looping over the string for i in string: # if the charcter is a digit, its added to temp at the units place - if (i.isdigit()): + if i.isdigit(): temp = temp * 10 + int(i) # else the result is addedc to the decoded string else: ans += i * temp temp = 0 - + return ans + # DRIVER CODE print(encode("AAAABBBCCDAA")) -print(decode("4A3B2C1D2A")) \ No newline at end of file +print(decode("4A3B2C1D2A")) diff --git a/Solutions/30.py b/Solutions/30.py index c215825..66b82e7 100644 --- a/Solutions/30.py +++ b/Solutions/30.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an array of non-negative integers that represents a two-dimensional elevation map where each element is unit-width wall and the integer is the height. @@ -9,15 +9,15 @@ [2, 1, 2] => 1 [3, 0, 1, 3, 0, 5] => 8 -''' +""" # FUNCTION TO PERFORM THE OPERATION def water(arr): # Checking if there is enough walls to store water length = len(arr) - if (length < 3): + if length < 3: return 0 - + # Variable to store the total amount of accumulated water total_water = 0 @@ -49,8 +49,9 @@ def water(arr): return total_water + # DRIVER CODE print(water([2, 1, 2])) print(water([3, 0, 1, 3, 0, 5])) print(water([5, 3, 5, 3, 4])) -print(water([5, 1, 1, 1, 0])) \ No newline at end of file +print(water([5, 1, 1, 1, 0])) diff --git a/Solutions/31.py b/Solutions/31.py index 2f5ab64..cb53474 100644 --- a/Solutions/31.py +++ b/Solutions/31.py @@ -1,4 +1,4 @@ -''' +""" Problem: The edit distance between two strings refers to the minimum number of character insertions, deletions, and substitutions required to change one string to the other. @@ -8,29 +8,31 @@ Input = “kitten”, “sitting” Output = 3 -''' +""" # FUNCTION TO PERFORM THE OPERATION def string_distance(str1, str2): # if the strings are same, the distance between the strings is 0 [BASE CASE FOR RECURSION] - if (str1 == str2): + if str1 == str2: return 0 # if str1 is an empty string, distance is length of str2 (len(str2) characters have to be inserted) [BASE CASE FOR RECURSION] - elif (not str1): + elif not str1: return len(str2) # if str2 is an empty string, distance is length of str1 (len(str1) characters have to be inserted) [BASE CASE FOR RECURSION] - elif (not str2): + elif not str2: return len(str1) # if the 1st character are the same for both strings - if (str1[0] == str2[0]): + if str1[0] == str2[0]: return string_distance(str1[1:], str2[1:]) # if the 1st character are different, we choose the minimum distance for 1st character deletion, addition and modifying the charcter + 1 (due to the change in the character) return 1 + min( - string_distance(str1[1:], str2), # deletion from str1 - string_distance(str1, str2[1:]), # addition to str1 - string_distance(str1[1:], str2[1:])) # modification to str1 + string_distance(str1[1:], str2), # deletion from str1 + string_distance(str1, str2[1:]), # addition to str1 + string_distance(str1[1:], str2[1:]), + ) # modification to str1 + # DRIVER CODE -print(string_distance('kitten', 'sitting')) \ No newline at end of file +print(string_distance("kitten", "sitting")) diff --git a/Solutions/32.py b/Solutions/32.py index 794d4f6..bf73977 100644 --- a/Solutions/32.py +++ b/Solutions/32.py @@ -1,6 +1,6 @@ # This program was not written by me, but this shows the implementation of Arbitrage well. -''' +""" Problem: Suppose you are given a table of currency exchange rates, represented as a 2D array. Determine whether there is a possible arbitrage. @@ -11,7 +11,7 @@ Input = [[1, 2], [0.5, 1]] Output = False -''' +""" from math import log @@ -23,7 +23,7 @@ def arbitrage(table): # get the right result source = 0 n = len(transformed_graph) - min_dist = [float('inf')] * n + min_dist = [float("inf")] * n min_dist[source] = 0 @@ -42,8 +42,7 @@ def arbitrage(table): return False + # DRIVER CODE print(arbitrage([[1, 2], [0.5, 1]])) -print(arbitrage([[1, 3, 4], - [2, 1, 3], - [5, 2, 1]])) \ No newline at end of file +print(arbitrage([[1, 3, 4], [2, 1, 3], [5, 2, 1]])) diff --git a/Solutions/33.py b/Solutions/33.py index 25a877b..91777e0 100644 --- a/Solutions/33.py +++ b/Solutions/33.py @@ -1,4 +1,4 @@ -''' +""" Problem: Compute the running median of a sequence of numbers. That is, given a stream of numbers, print out the median of the list so far on each new element. @@ -7,7 +7,7 @@ Example: Input = [2, 1, 5, 7, 2, 0, 5] Output = [2, 1.5, 2, 3.5, 2, 2, 2] -''' +""" # Helper function to perform insertion sort on the current position (as its applied one after another, so results in a sorted array at the end) def ins_sort(Arr, element, pos): @@ -16,13 +16,14 @@ def ins_sort(Arr, element, pos): # Looping over till the left of the Array is sorted for i in range(pos, 0, -1): - if (Arr[i] < Arr[i-1]): - Arr[i], Arr[i-1] = Arr[i-1], Arr[i] + if Arr[i] < Arr[i - 1]: + Arr[i], Arr[i - 1] = Arr[i - 1], Arr[i] else: break - + return Arr + # FUNCTION TO PERFORM THE OPERATION def running_median(Arr, length): # Ans: stores the running median @@ -39,14 +40,15 @@ def running_median(Arr, length): pos += 1 # Calulating and storing the running median - if (pos % 2 != 0): - Ans[pos-1] = temp[pos//2] + if pos % 2 != 0: + Ans[pos - 1] = temp[pos // 2] else: - Ans[pos-1] = (temp[pos//2] + temp[pos//2 - 1]) / 2 - + Ans[pos - 1] = (temp[pos // 2] + temp[pos // 2 - 1]) / 2 + return Ans + # DRIVER CODE inp = [2, 1, 5, 7, 2, 0, 5] ans = running_median(inp, len(inp)) -print(("{:.2f}\t" * len(ans)).format(*ans)) \ No newline at end of file +print(("{:.2f}\t" * len(ans)).format(*ans)) diff --git a/Solutions/34.py b/Solutions/34.py index 9853440..2e11dc5 100644 --- a/Solutions/34.py +++ b/Solutions/34.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string, find the palindrome that can be made by inserting the fewest number of characters as possible anywhere in the word. @@ -7,7 +7,7 @@ Example: "race" => "ecarace" "google" => "elgoogle" -''' +""" # FUNCTION TO PERFORM THE OPERATION def nearest_palindrome(string): @@ -15,31 +15,32 @@ def nearest_palindrome(string): length = len(string) # if the passed string is already a palindrome, the string is returned - if (string[::-1] == string): + if string[::-1] == string: return string # if the first and last characters are same, the function is called recursively on the string without the first and last charater # this is allowed as insertion anywhere in the word is allowed - if (string[0] == string[-1]): - return (string[0] + nearest_palindrome(string[1:length-1]) + string[0]) - + if string[0] == string[-1]: + return string[0] + nearest_palindrome(string[1 : length - 1]) + string[0] + else: # if the first and last characters are different, the resultant strings are calculated by adding the 1st character (pal_1) and last charcter (pal_2) pal_1 = string[0] + nearest_palindrome(string[1:]) + string[0] - pal_2 = string[-1] + nearest_palindrome(string[:length-1]) + string[-1] - + pal_2 = string[-1] + nearest_palindrome(string[: length - 1]) + string[-1] + # if one of the string is shorter, it is returned - if (len(pal_1) > len(pal_2)): + if len(pal_1) > len(pal_2): return pal_2 - elif (len(pal_1) < len(pal_2)): + elif len(pal_1) < len(pal_2): return pal_1 # if both strings have the same length, the lexicographically earliest one is returned - if (pal_1 < pal_2): + if pal_1 < pal_2: return pal_1 else: return pal_2 + # DRIVER CODE print(nearest_palindrome("race")) -print(nearest_palindrome("google")) \ No newline at end of file +print(nearest_palindrome("google")) diff --git a/Solutions/35.py b/Solutions/35.py index 41e57e8..c19dc9d 100644 --- a/Solutions/35.py +++ b/Solutions/35.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of strictly the characters 'R', 'G', and 'B', segregate the values of the array so that all the Rs come first, the Gs come second, and the Bs come last. You can only swap elements of the array. @@ -6,7 +6,7 @@ Example: ['G', 'B', 'R', 'R', 'B', 'R', 'G'] => ['R', 'R', 'R', 'G', 'G', 'B', 'B'] -''' +""" # FUNCTION TO PERFORM THE OPERATION def segregate(Arr, length): @@ -16,19 +16,20 @@ def segregate(Arr, length): # 1st pass for segregating "R"s for i in range(length): # if a "R" is encountered, it is swapped with the element at the index pos and pos is incremented - if (Arr[i] == "R"): + if Arr[i] == "R": Arr[i], Arr[pos] = Arr[pos], Arr[i] pos += 1 - + # 1st pass for segregating "G"s for i in range(pos, length): # if a "G" is encountered, it is swapped with the element at the index pos and pos is incremented - if (Arr[i] == "G"): + if Arr[i] == "G": Arr[i], Arr[pos] = Arr[pos], Arr[i] pos += 1 - + return Arr + # DRIVER CODE -inp = ['G', 'B', 'R', 'R', 'B', 'R', 'G'] -print(segregate(inp, len(inp))) \ No newline at end of file +inp = ["G", "B", "R", "R", "B", "R", "G"] +print(segregate(inp, len(inp))) diff --git a/Solutions/36.py b/Solutions/36.py index f15c29c..2558067 100644 --- a/Solutions/36.py +++ b/Solutions/36.py @@ -1,8 +1,8 @@ -''' +""" Problem: Given the root to a binary search tree, find the second largest node in the tree. -''' +""" # Local Import from the datastructure module from DataStructures.Tree import Node, Binary_Search_Tree @@ -10,40 +10,42 @@ # Helper function to get the largest node and parent def get_largest(node): # if there is no node, None is returned - if (node == None): + if node == None: return None - + # parent is set to None (if the root is the largest node, parent is returned as None) parent = None # getting the right-most node (largest node as its a Binary Search Tree) - while (node.right): + while node.right: parent = node node = node.right - + # both the parent and the node is returned return (parent, node) + # FUNCTION TO PERFORM THE OPERATION def second_largest(tree): # if the tree is empty, None is returned - if (tree.root == None): + if tree.root == None: return None - + # finding the largest node largest_parent, largest = get_largest(tree.root) - + # if the largest node has a left node, the largest child of the left node is the 2nd largest node (BST property) - if (largest.left): + if largest.left: return (get_largest(largest.left)[1]).val - + # if the left node is absent and so is the parent (the tree contains only 1 node), None is returned - elif (largest_parent == None): + elif largest_parent == None: return None - + # if the largest parent is present its the 2nd largest node if no left node is present (BST property) return (largest_parent).val + # DRIVER CODE tree = Binary_Search_Tree() tree.add(5) @@ -54,4 +56,4 @@ def second_largest(tree): tree.add(7) tree.add(9) -print(second_largest(tree)) \ No newline at end of file +print(second_largest(tree)) diff --git a/Solutions/37.py b/Solutions/37.py index 2e64e46..6f773bc 100644 --- a/Solutions/37.py +++ b/Solutions/37.py @@ -1,4 +1,4 @@ -''' +""" Problem: The power set of a set is the set of all its subsets. Write a function that, given a set, generates its power set. @@ -6,7 +6,7 @@ Example: {1, 2, 3} => {{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}} -''' +""" # FUNCTION TO PERFORM THE OPERATION def power_set_calc(arr): @@ -17,13 +17,14 @@ def power_set_calc(arr): for i in arr: for index in range(len(power_set)): # temp stores a copy of the element under consideration - temp = (list(power_set[index])) + temp = list(power_set[index]) # the current array element is added to temp temp.append(i) # the generated temp is added to the power_set power_set.append(temp) - + return power_set + # DRIVER CODE -print(power_set_calc([1,2,3])) +print(power_set_calc([1, 2, 3])) diff --git a/Solutions/38.py b/Solutions/38.py index e54c2d3..a5f62e0 100644 --- a/Solutions/38.py +++ b/Solutions/38.py @@ -1,7 +1,7 @@ # NOTE: This solution is given by the Daily Coding Problem # This is a Classic Backtracking Problem, it has several solution methodologies but all use backtracking -''' +""" Problem: You have an N by N board. @@ -12,11 +12,11 @@ Input = 4 Output = 2 -''' +""" # FUNCTION TO PERFORM THE OPERATION def n_queens(n, board=[]): - if (n == len(board)): + if n == len(board): return 1 count = 0 @@ -24,12 +24,13 @@ def n_queens(n, board=[]): for col in range(n): board.append(col) - if (is_valid(board)): + if is_valid(board): count += n_queens(n, board) board.pop() return count + # Helper function to check any queens can attack the last queen. def is_valid(board): current_queen_row, current_queen_col = len(board) - 1, board[-1] @@ -37,10 +38,11 @@ def is_valid(board): for row, col in enumerate(board[:-1]): diff = abs(current_queen_col - col) - if (diff == 0 or diff == current_queen_row - row): + if diff == 0 or diff == current_queen_row - row: return False - + return True + # DRIVER CODE -print(n_queens(4)) \ No newline at end of file +print(n_queens(4)) diff --git a/Solutions/39.py b/Solutions/39.py index 906288c..5cc9c63 100644 --- a/Solutions/39.py +++ b/Solutions/39.py @@ -1,6 +1,6 @@ # NOTE: The code is a bit messy as I finished it in a rush -''' +""" Problem: Conway's Game of Life takes place on an infinite two-dimensional board of square cells. @@ -17,37 +17,38 @@ Once initialized, it should print out the board state at each step. Since it's an infinite board, print out only the relevant coordinates, i.e. from the top-leftmost live cell to bottom-rightmost live cell. You can represent a live cell with an asterisk (*) and a dead cell with a dot (.). -''' +""" # Coordinate Object -class Coordinate(): +class Coordinate: # Initialization function def __init__(self, x, y): self.x = x self.y = y self.coordinate = (x, y) - + # String function def __str__(self): return f"({self.x}, {self.y})" - + # Representation function def __repr__(self): return self.__str__() - + # Function to return all the neighbours in x-y plane def get_neighbours(self): return [ - Coordinate(self.x-1, self.y), - Coordinate(self.x-1, self.y+1), - Coordinate(self.x, self.y+1), - Coordinate(self.x+1, self.y+1), - Coordinate(self.x+1, self.y), - Coordinate(self.x+1, self.y-1), - Coordinate(self.x, self.y-1), - Coordinate(self.x-1, self.y-1), + Coordinate(self.x - 1, self.y), + Coordinate(self.x - 1, self.y + 1), + Coordinate(self.x, self.y + 1), + Coordinate(self.x + 1, self.y + 1), + Coordinate(self.x + 1, self.y), + Coordinate(self.x + 1, self.y - 1), + Coordinate(self.x, self.y - 1), + Coordinate(self.x - 1, self.y - 1), ] + # Function to display the board def show_board(alive_cells): # Variables to store the minimum and maximum x and y coordinates @@ -58,102 +59,125 @@ def show_board(alive_cells): # Getting the actual value for x_max, x_min, y_max and y_min for cell in alive_cells: - if (cell[0] > x_max): + if cell[0] > x_max: x_max = cell[0] - if (cell[0] < x_min): + if cell[0] < x_min: x_min = cell[0] - if (cell[1] > y_max): + if cell[1] > y_max: y_max = cell[1] - if (cell[1] < y_min): + if cell[1] < y_min: y_min = cell[1] - + # Printing the state of the board (in the region under consideration - live cells present) - for x in range(x_min, x_max+1): - for y in range(y_min, y_max+1): - if ((x, y) in alive_cells): + for x in range(x_min, x_max + 1): + for y in range(y_min, y_max + 1): + if (x, y) in alive_cells: print("*", end=" ") else: print(".", end=" ") print() print() + # FUNCTION TO PERFORM THE OPERATION def play_game(board, n): # Alive cells is a set of tuples having the coordinates of the live cells alive_cells = set([cell.coordinate for cell in board]) print("Initail Board of Game of Life:") show_board(alive_cells) - + # Running the game for n iterations - for i in range(1, n+1): + for i in range(1, n + 1): # dead stores the coordinates of the cells which die in the current iterations # alive stores the coordinates of the cells which come alive in the current iterations dead = [] alive = [] - + # Looping over the alive cells for cell in alive_cells: # alive neighbours contains the number of alive neighbours of a cell alive_neighbours = 0 # list of all neighbours - neighbours = [cell_neighbour.coordinate for cell_neighbour in Coordinate(cell[0], cell[1]).get_neighbours()] + neighbours = [ + cell_neighbour.coordinate + for cell_neighbour in Coordinate(cell[0], cell[1]).get_neighbours() + ] # checking how many neighbours the cell has for neighbour in neighbours: - if (neighbour in alive_cells): + if neighbour in alive_cells: alive_neighbours += 1 - + # if the cell is supposed to die, adding to the dead list (as cannot change alive cells in runtime) - if (alive_neighbours < 2 or alive_neighbours > 3): + if alive_neighbours < 2 or alive_neighbours > 3: dead.append(cell) - + # Removing dead cells for cell in dead: alive_cells.remove(cell) - + # Looping over the alive cells for cell in alive_cells: # list of all neighbours - neighbours = [cell_neighbour.coordinate for cell_neighbour in Coordinate(cell[0], cell[1]).get_neighbours()] - + neighbours = [ + cell_neighbour.coordinate + for cell_neighbour in Coordinate(cell[0], cell[1]).get_neighbours() + ] + # Looping over the dead cells with live neighbours for neighbour in neighbours: - if (neighbour not in alive_cells): + if neighbour not in alive_cells: # list of all neighbours of dead cells with live neighbours - neighbour_neighbours = [cell_neighbour.coordinate for cell_neighbour in Coordinate(neighbour[0], neighbour[1]).get_neighbours()] + neighbour_neighbours = [ + cell_neighbour.coordinate + for cell_neighbour in Coordinate( + neighbour[0], neighbour[1] + ).get_neighbours() + ] alive_neighbours = 0 # Getting the number of live neighbours for neighbour_neighbour in neighbour_neighbours: - if (neighbour_neighbour in alive_cells): + if neighbour_neighbour in alive_cells: alive_neighbours += 1 - + # if the cell is supposed to come alive, adding to the alive list (as cannot change alive cells in runtime) - if (alive_neighbours == 3): + if alive_neighbours == 3: alive.append(neighbour) - + # Adding new live cells for cell in alive: alive_cells.add(cell) - + # Displaying results print(f"Iteration {i}:") show_board(alive_cells) + # DRIVER CODE -board_0 = [ - Coordinate(0, 0), Coordinate(1, 0), Coordinate(1, 1), Coordinate(1, 5)] +board_0 = [Coordinate(0, 0), Coordinate(1, 0), Coordinate(1, 1), Coordinate(1, 5)] play_game(board_0, 3) board_1 = [ - Coordinate(0, 0), Coordinate(1, 0), Coordinate(1, 1), Coordinate(1, 5), - Coordinate(2, 5), Coordinate(2, 6)] + Coordinate(0, 0), + Coordinate(1, 0), + Coordinate(1, 1), + Coordinate(1, 5), + Coordinate(2, 5), + Coordinate(2, 6), +] play_game(board_1, 4) board_2 = [ - Coordinate(0, 0), Coordinate(1, 0), Coordinate(1, 1), - Coordinate(2, 5), Coordinate(2, 6), Coordinate(3, 9), - Coordinate(4, 8), Coordinate(5, 10)] -play_game(board_2, 4) \ No newline at end of file + Coordinate(0, 0), + Coordinate(1, 0), + Coordinate(1, 1), + Coordinate(2, 5), + Coordinate(2, 6), + Coordinate(3, 9), + Coordinate(4, 8), + Coordinate(5, 10), +] +play_game(board_2, 4) diff --git a/Solutions/40.py b/Solutions/40.py index 7a2ac49..0d5a33f 100644 --- a/Solutions/40.py +++ b/Solutions/40.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of integers where every integer occurs three times except for one integer, which only occurs once, find and return the non-duplicated integer. @@ -6,9 +6,9 @@ Example: [6, 1, 3, 3, 3, 6, 6] => 1 -''' +""" -# We can sum the bits in same positions for all the numbers and take modulo with 3. +# We can sum the bits in same positions for all the numbers and take modulo with 3. # The bits for which sum is not multiple of 3, are the bits of number with single occurrence. # Let us consider the example array {9, 8, 9, 9}. The 1001, 1000, 1001, 1001 # Sum of first bits (2 ^ 0) % 3 = (1 + 1 + 1 + 0) % 3 = 0 @@ -21,27 +21,28 @@ def get_unique(arr): # Variable to store the element which occours once unique_elem = 0 - + # Iterate through all the bits (considering a 64 bit machine) for i in range(64): # sum_i_pos_bits stores the sum of the masked position bits of all elements in the array # mask stores the current mask (example of a 4 bit mask for 2nd pos: 0100 and for 1st pos: 0010) sum_i_pos_bits = 0 - mask = (1 << i) + mask = 1 << i # Calculating the sum_i_pos_bits for the current mask - for elem in arr: - if (elem & mask): + for elem in arr: + if elem & mask: sum_i_pos_bits = sum_i_pos_bits + 1 - + # If the sum_i_pos_bits is 1 (implies the unique element contains 1 in that position), adding it to the unique_elem - if (sum_i_pos_bits % 3) : - unique_elem = unique_elem | mask - - return unique_elem + if sum_i_pos_bits % 3: + unique_elem = unique_elem | mask + + return unique_elem + # DRIVER CODE -arr = [3, 3, 2, 3] +arr = [3, 3, 2, 3] print(get_unique(arr)) arr = [13, 19, 13, 13] @@ -50,5 +51,5 @@ def get_unique(arr): arr = [6, 1, 3, 3, 3, 6, 6] print(get_unique(arr)) -arr = [12, 1, 3, 1, 1, 2, 3, 2, 2, 3] -print(get_unique(arr)) \ No newline at end of file +arr = [12, 1, 3, 1, 1, 2, 3, 2, 2, 3] +print(get_unique(arr)) diff --git a/Solutions/41.py b/Solutions/41.py index 4cf4d57..efce432 100644 --- a/Solutions/41.py +++ b/Solutions/41.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an unordered list of flights taken by someone, each represented as (origin, destination) pairs, and a starting airport, compute the person's itinerary. @@ -10,15 +10,15 @@ [('SFO', 'HKO'), ('YYZ', 'SFO'), ('YUL', 'YYZ'), ('HKO', 'ORD')], 'YUL' => ['YUL', 'YYZ', 'SFO', 'HKO', 'ORD'] [('SFO', 'COM'), ('COM', 'YYZ')], 'COM' => None [('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'A')], 'A' => ['A', 'B', 'C', 'A', 'C'] -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_itinerary(flights, starting_point, current_itinerary=[]): # Base case of recursion (all flights except the final destination has been added) - if (not flights and current_itinerary): + if not flights and current_itinerary: return current_itinerary + [starting_point] # if no flights are provided, None is returned - elif (not flights): + elif not flights: return None # resulatant_itinerary stores the final result @@ -27,16 +27,26 @@ def get_itinerary(flights, starting_point, current_itinerary=[]): # iterating over the flight list for index, (src, dest) in enumerate(flights): # if the starting point is found the iternary using that destination is calculated (DFS) - if (starting_point == src): - child_itinerary = get_itinerary(flights[:index] + flights[index + 1:], dest, current_itinerary + [src]) + if starting_point == src: + child_itinerary = get_itinerary( + flights[:index] + flights[index + 1 :], dest, current_itinerary + [src] + ) # if the child_itinerary is a vaild itinerary and lexicographically smaller, the resulatant_itinerary is updated - if (child_itinerary and (not resulatant_itinerary or ("".join(child_itinerary) < "".join(resulatant_itinerary)))): + if child_itinerary and ( + not resulatant_itinerary + or ("".join(child_itinerary) < "".join(resulatant_itinerary)) + ): resulatant_itinerary = child_itinerary return resulatant_itinerary + # DRIVER CODE -print(get_itinerary([('SFO', 'HKO'), ('YYZ', 'SFO'), ('YUL', 'YYZ'), ('HKO', 'ORD')], "YUL")) -print(get_itinerary([('SFO', 'COM'), ('COM', 'YYZ')], "COM")) -print(get_itinerary([('A', 'B'), ('A', 'C'), ('B', 'C'), ('C', 'A')], "A")) \ No newline at end of file +print( + get_itinerary( + [("SFO", "HKO"), ("YYZ", "SFO"), ("YUL", "YYZ"), ("HKO", "ORD")], "YUL" + ) +) +print(get_itinerary([("SFO", "COM"), ("COM", "YYZ")], "COM")) +print(get_itinerary([("A", "B"), ("A", "C"), ("B", "C"), ("C", "A")], "A")) diff --git a/Solutions/42.py b/Solutions/42.py index f99e4b6..59749ea 100644 --- a/Solutions/42.py +++ b/Solutions/42.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of integers S and a target number k, write a function that returns a subset of S that adds up to k. @@ -7,29 +7,30 @@ Example: [12, 1, 61, 5, 9, 2], 24 => [12, 9, 2, 1] -''' +""" # FUNCTION TO PERFORM THE OPERATION def target_sum(arr, k): # Recursion Base Case 1 (Empty arr) - if (not arr): + if not arr: return None - + # Recursion Base Case 2 (Target sum = the 1st element of array) - elif (arr[0] == k): + elif arr[0] == k: return [arr[0]] - + # Recursive call (considering arr[0] is included in the subset summing to k) - temp = target_sum(arr[1:], k-arr[0]) + temp = target_sum(arr[1:], k - arr[0]) # if the function returns a list, arr[0] is added to it and returned - if (temp): + if temp: return [arr[0]] + temp # if the function returns None, the result of the recursive call (considering arr[0] is excluded in the subset summing to k) return target_sum(arr[1:], k) + # DRIVER CODE print(target_sum([12, 1, 61, 5, 9, 2], 24)) print(target_sum([12, 1, 61, 5, 9, 2], 61)) print(target_sum([12, 1, 61, 5, -108, 2], -106)) -print(target_sum([12, 1, 61, 5, -108, 2], 1006)) \ No newline at end of file +print(target_sum([12, 1, 61, 5, -108, 2], 1006)) diff --git a/Solutions/43.py b/Solutions/43.py index d7743a9..16c1c41 100644 --- a/Solutions/43.py +++ b/Solutions/43.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement a stack that has the following methods: @@ -9,52 +9,58 @@ If there are no elements in the stack, then it should throw an error or return null. Each method should run in constant time. -''' +""" # STACK CLASS -class Stack(): +class Stack: # Initialize function (Automatically called upon creating an object instance) def __init__(self): # stack: stores the stack # maximum: stores the all the maxima till the given point self.stack = [] self.maximum = [] - + # String function (Automatically called upon converting to string, generally used when printing) def __str__(self): - return ("Stack: " + ("{} " * len(self.stack)) + "\nMax Stack: " + ("{} " * len(self.maximum))).format(*self.stack, *self.maximum) - + return ( + "Stack: " + + ("{} " * len(self.stack)) + + "\nMax Stack: " + + ("{} " * len(self.maximum)) + ).format(*self.stack, *self.maximum) + # FUNCTION TO PERFORM THE OPERATION (push) def push(self, val): # Adding the value to the stack self.stack.append(val) # if the current value is larger than the previous maxima, its added to the maximum list - if (not self.maximum or self.stack[self.maximum[-1]] < val): - self.maximum.append(len(self.stack)-1) - + if not self.maximum or self.stack[self.maximum[-1]] < val: + self.maximum.append(len(self.stack) - 1) + # FUNCTION TO PERFORM THE OPERATION (pop) def pop(self): # if the stack is empty, None is returned - if (not self.stack): + if not self.stack: return None - + # if the current element to be removed is in the maximum list, its removed - if (len(self.stack) == self.maximum[-1]+1): + if len(self.stack) == self.maximum[-1] + 1: self.maximum.pop() - + # the last element is returned return self.stack.pop() - + # FUNCTION TO PERFORM THE OPERATION (max) def max(self): # if the stack is empty, None is returned - if (not self.stack): + if not self.stack: return None - + # the value at the position (self.maximum[-1]) is returned as the maximum list stores the addresses return self.stack[self.maximum[-1]] + # DRIVER CODE s = Stack() s.push(1) @@ -75,4 +81,4 @@ def max(self): print(s.pop()) print(s.max()) print(s) -print(s.pop()) \ No newline at end of file +print(s.pop()) diff --git a/Solutions/44.py b/Solutions/44.py index d6f30a2..5435cab 100644 --- a/Solutions/44.py +++ b/Solutions/44.py @@ -1,4 +1,4 @@ -''' +""" Problem: We can determine how "out of order" an array A is by counting the number of inversions it has. @@ -10,7 +10,7 @@ Example: [2, 4, 1, 3, 5] => 3 <(2, 1), (4, 1), and (4, 3)> [5, 4, 3, 2, 1] => 10 -''' +""" # Helper's helper function (merge function to merge the segments broken up by the merge_sort function) def merge(a_with_inv, b_with_inv): @@ -31,9 +31,9 @@ def merge(a_with_inv, b_with_inv): inversions = a_inv + b_inv # Creating the merged arr till the elements on left or the right arr run out - while (i < len(a) and j < len(b)): + while i < len(a) and j < len(b): # Adding the smaller element to the merged arr and incrementing the corresponding index (i or j) - if (a[i] < b[j]): + if a[i] < b[j]: merged.append(a[i]) i += 1 else: @@ -43,22 +43,23 @@ def merge(a_with_inv, b_with_inv): j += 1 # Adding the elements of the array where the elements haven't been processed yet - while (i < len(a)): + while i < len(a): merged.append(a[i]) i += 1 - while (j < len(b)): + while j < len(b): merged.append(b[j]) j += 1 return merged, inversions + # Helper function (uses merge sort to calculate the number of inversions in O(nlog(n))) def merge_sort(arr): # Getting the length of the arr length = len(arr) # if the array has 0 or 1 element, no inversion is possible - if (length in (0, 1)): + if length in (0, 1): return arr, 0 # Getting the mid @@ -68,15 +69,17 @@ def merge_sort(arr): return merged_array, inversions + # FUNCTION TO PERFORM THE OPERATION def count_inversions(arr): # Calling merge_sort on the arr to get the sorted arr and inversions _sorted_arr, inversions = merge_sort(arr) return inversions + # DRIVER CODE print(count_inversions([1, 2, 3, 4, 5])) print(count_inversions([2, 1, 3, 4, 5])) print(count_inversions([2, 4, 1, 3, 5])) print(count_inversions([2, 6, 1, 3, 7])) -print(count_inversions([5, 4, 3, 2, 1])) \ No newline at end of file +print(count_inversions([5, 4, 3, 2, 1])) diff --git a/Solutions/45.py b/Solutions/45.py index 8fc6db3..789b4b1 100644 --- a/Solutions/45.py +++ b/Solutions/45.py @@ -1,12 +1,13 @@ -''' +""" Problem: You have a function rand5() that returns an integer from 1 to 5 (inclusive) with uniform probability. Implement a function rand7() that returns an integer from 1 to 7 (inclusive) using rand5(). -''' +""" # Library Imports (matplotlib is not mandatory, it is used to plot the distribution of the generated random numbers from 1 to 7) from random import randint + # You can either install matplotlib using 'pip install matplotlib' in CMD/Terminal/PowerShell # or comment out any line containing 'plt' import matplotlib.pyplot as plt @@ -15,6 +16,7 @@ def rand5(): return randint(1, 5) + # FUNCTION TO PERFORM THE OPERATION def rand7(): # Generating 2 numbers between 1 and 5 @@ -26,10 +28,11 @@ def rand7(): # if the number is NOT in the range[1, 21], rand7 is called and the result returned (as in 1 to 21, mod 7 yield all numbers from 0 to 6 with equal probability) # else (temp % 7) gives a number between 0 to 6, and the incremented result (range: 1 to 7) is returned - if (temp <= 21): - return ((temp % 7) + 1) + if temp <= 21: + return (temp % 7) + 1 return rand7() + # This Section is just for displaying the distribution, it can be commented out # result stores the result of the rand7 function result = [] @@ -40,4 +43,4 @@ def rand7(): # Plotting the distribution plt.hist(result, 7, edgecolor="black") -plt.show() \ No newline at end of file +plt.show() diff --git a/Solutions/46.py b/Solutions/46.py index 0936538..bca6ff4 100644 --- a/Solutions/46.py +++ b/Solutions/46.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string, find the longest palindromic contiguous substring. @@ -8,29 +8,31 @@ "aabcdcb" => "bcdcb" "bananas" => "anana" -''' +""" # Function to check if a string is a palindrome def palindrome_check(string): - return (string == string[::-1]) + return string == string[::-1] + # FUNCTION TO PERFORM THE OPERATION def longest_palindrome_substring(string): # if the string is a palindrome, it is returned (BASE CASE FOR RECURSION) - if (palindrome_check(string)): + if palindrome_check(string): return string - + # string1 removes the 1st character in the string and calls the function recursively # string2 removes the last character in the string and calls the function recursively string1 = longest_palindrome_substring(string[1:]) string2 = longest_palindrome_substring(string[:-1]) # The longer palindromic substring is returned - if (len(string1) > len(string2)): + if len(string1) > len(string2): return string1 else: return string2 + # DRIVER CODE print(longest_palindrome_substring("aabcdcb")) -print(longest_palindrome_substring("bananas")) \ No newline at end of file +print(longest_palindrome_substring("bananas")) diff --git a/Solutions/47.py b/Solutions/47.py index 9e61ccf..a715c72 100644 --- a/Solutions/47.py +++ b/Solutions/47.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given a array of numbers representing the stock prices of a company in chronological order. @@ -8,7 +8,7 @@ Example: [9, 11, 8, 5, 7, 10] => 5 (since you could buy the stock at 5 dollars and sell it at 10 dollars) -''' +""" # FUNCTION TO PERFORM THE OPERATION def max_diff(Arr): @@ -16,7 +16,7 @@ def max_diff(Arr): length = len(Arr) # If there are less than 2 elements, buying and selling is not possible - if (length < 2): + if length < 2: return None # min_element: stores the minimum element till the current position (initialized with Arr[0]) @@ -27,17 +27,18 @@ def max_diff(Arr): # Iterating over the array for i in range(1, length): # If the current element is smaller than the min_element, its updated - if (min_element > Arr[i]): + if min_element > Arr[i]: min_element = Arr[i] # If the difference is larger than the current difference, its updated - elif (diff < (Arr[i] - min_element)): - diff = (Arr[i] - min_element) - + elif diff < (Arr[i] - min_element): + diff = Arr[i] - min_element + # Incase there is negative difference, 0 is returned, else the max difference is returned return max(0, diff) + # DRIVER CODE print(max_diff([9, 11, 8, 5, 7, 10])) print(max_diff([1, 2, 3, 4, 5])) print(max_diff([5, 4, 3, 2, 1])) -print(max_diff([1000])) \ No newline at end of file +print(max_diff([1000])) diff --git a/Solutions/48.py b/Solutions/48.py index 1ff501a..ebcd296 100644 --- a/Solutions/48.py +++ b/Solutions/48.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given pre-order and in-order traversals of a binary tree, write a function to reconstruct the tree. @@ -10,7 +10,7 @@ b c / \ / \ d e f g -''' +""" # Local Import from the datastructure module from DataStructures.Tree import Binary_Tree, Node @@ -21,26 +21,26 @@ def tree_gen(preorder, inorder): length = len(preorder) # if the preorder and inorder expressions has different number of nodes RuntimeError is raised - if (length != len(inorder)): + if length != len(inorder): raise RuntimeError # if there are no nodes, an empty tree is returned - if (length == 0): + if length == 0: return Binary_Tree(None) - + # starting with the root root = preorder[0] tree = Binary_Tree(root) # if there are more nodes, the function is called recursively - if (length > 1): + if length > 1: # finding the index of the root in the inorder expression ind = inorder.index(root) # partitioning the nodes as per the branch - temp_left = (inorder[:ind], preorder[1:ind+1]) - temp_right = (inorder[ind+1:], preorder[ind+1:]) - + temp_left = (inorder[:ind], preorder[1 : ind + 1]) + temp_right = (inorder[ind + 1 :], preorder[ind + 1 :]) + # creating a tree for each branch tree_left = tree_gen(temp_left[1], temp_left[0]) tree_right = tree_gen(temp_right[1], temp_right[0]) @@ -48,13 +48,16 @@ def tree_gen(preorder, inorder): # attaching the sub-tree to their respective branch tree.root.left = tree_left.root tree.root.right = tree_right.root - + # the final tree is returned return tree + # DRIVER CODE -test1 = tree_gen(["a", "b", "d", "e", "c", "f", "g"], ["d", "b", "e", "a", "f", "c", "g"]) +test1 = tree_gen( + ["a", "b", "d", "e", "c", "f", "g"], ["d", "b", "e", "a", "f", "c", "g"] +) print(test1) test2 = tree_gen(["a", "b", "d", "e", "c", "f"], ["d", "b", "e", "a", "f", "c"]) -print(test2) \ No newline at end of file +print(test2) diff --git a/Solutions/49.py b/Solutions/49.py index b012fff..c230735 100644 --- a/Solutions/49.py +++ b/Solutions/49.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of numbers, find the maximum sum of any contiguous subarray of the array. @@ -7,7 +7,7 @@ Example: [34, -50, 42, 14, -5, 86] => 137 [-5, -1, -8, -9] => 0 -''' +""" # FUNCTION TO PERFORM THE OPERATION def max_cont_sum(Arr): @@ -20,29 +20,30 @@ def max_cont_sum(Arr): # looping over and modifying the list (Arr[i] is the sum of all the elements till i. Eg: [1, 2, 3] => [1, 3, 6]) for i in range(1, length): - Arr[i] = Arr[i] + Arr[i-1] - + Arr[i] = Arr[i] + Arr[i - 1] + # looping over the list and updating min_loc and max_loc for i in range(length): # min_loc updation - if (Arr[min_loc] > Arr[i]): + if Arr[min_loc] > Arr[i]: min_loc = i - + # min_loc updation - elif (Arr[max_loc] < Arr[i]): + elif Arr[max_loc] < Arr[i]: max_loc = i - + # if the value if at max_loc is negative, all the elements are negative, 0 is returned - if (Arr[max_loc] > 0): + if Arr[max_loc] > 0: # if min_loc is 0 and the element is positive, all the elements till max_loc is is the max sub arr, so Arr[max_loc] is returned - if ((min_loc == 0) and (Arr[0] > 0)): + if (min_loc == 0) and (Arr[0] > 0): return Arr[max_loc] # else Arr[max_loc] - Arr[min_loc] is returned - return (Arr[max_loc] - Arr[min_loc]) + return Arr[max_loc] - Arr[min_loc] else: return 0 + # DRIVER CODE print(max_cont_sum([34, -50, 42, 14, -5, 86])) print(max_cont_sum([-5, -1, -8, -9])) -print(max_cont_sum([5, 1, 8, 9])) \ No newline at end of file +print(max_cont_sum([5, 1, 8, 9])) diff --git a/Solutions/50.py b/Solutions/50.py index 6d864df..ed5831f 100644 --- a/Solutions/50.py +++ b/Solutions/50.py @@ -1,4 +1,4 @@ -''' +""" Problem: Suppose an arithmetic expression is given as a binary tree. Each leaf is an integer and each internal node is one of '+', '−', '∗', or '/' @@ -11,7 +11,7 @@ / \ / \ 3 2 4 5 => 45 [(3 + 2) * (4 + 5)] -''' +""" # local imports from DataStructures.Tree import Binary_Tree, Node @@ -19,16 +19,23 @@ # functions for operations to be performed # addition def add(num1, num2): - return (num1 + num2) + return num1 + num2 + + # subtraction def sub(num1, num2): - return (num1 - num2) + return num1 - num2 + + # multiplication def mul(num1, num2): - return (num1 * num2) + return num1 * num2 + + # division def div(num1, num2): - return (num1 / num2) + return num1 / num2 + # mapping the functions to the corresponding symbols OPERATIONS_DICT = {"+": add, "-": sub, "*": mul, "/": div} @@ -38,36 +45,38 @@ class Node_modified(Node): # using default init def __init__(self, val, left=None, right=None): Node.__init__(self, val, left, right) - + # transform helper function: transforms the symbols to the corresponding function from the mapping def transform(self): # if the symbol is in the map, the value of the node is overwritten with the function - if (self.val in OPERATIONS_DICT): + if self.val in OPERATIONS_DICT: self.val = OPERATIONS_DICT[self.val] - + # recursive call on children (can only happen if its a valid operation) self.left.transform() self.right.transform() - + # actual function to calculate the result from the expression tree def calculate(self): # if the current node holds a function, its applied on its children recursively - if (callable(self.val)): + if callable(self.val): return self.val(self.left.calculate(), self.right.calculate()) # if the current node holds a value, its returned else: return self.val + # FUNCTION TO PERFORM THE OPERATION def calc(root): # if the root node is present (!= None), its transformed and the expression is calculated - if (root): + if root: root.transform() return root.calculate() # if root doesn't exist, None is returned else: return None + # DRIVER CODE tree = Binary_Tree() tree.root = Node_modified("*") @@ -78,4 +87,4 @@ def calc(root): tree.root.right.left = Node_modified(4) tree.root.right.right = Node_modified(5) -print(calc(tree.root)) \ No newline at end of file +print(calc(tree.root)) diff --git a/Solutions/51.py b/Solutions/51.py index d3e4685..46b98b4 100644 --- a/Solutions/51.py +++ b/Solutions/51.py @@ -1,11 +1,11 @@ -''' +""" Problem: You have a function that generates perfectly random numbers between 1 and k (inclusive), where k is an input. Write a function that shuffles a deck of cards represented as an array using only swaps. It should run in O(N) time. Hint: Make sure each one of the 52! permutations of the deck is equally likely. -''' +""" # library import from random import randint @@ -31,6 +31,7 @@ def swap(): # returning the randomized sequence return arr + # DRIVER CODE print(*swap()) -print(*swap()) \ No newline at end of file +print(*swap()) diff --git a/Solutions/52.py b/Solutions/52.py index 181dec7..c189025 100644 --- a/Solutions/52.py +++ b/Solutions/52.py @@ -1,4 +1,4 @@ -''' +""" Problem: This problem was asked by Google. @@ -8,18 +8,19 @@ * get(key): gets the value at key. If no such key exists, return null. Each operation should run in O(1) time. -''' +""" # Node class for Double Linked List -class Node(): +class Node: def __init__(self, key, val): self.key = key self.val = val self.last = None self.next = None + # LRU Cache class -class LRU_Cache(): +class LRU_Cache: # initialize method def __init__(self, size): # head and rear store the head and the rear of the double linked list @@ -33,7 +34,7 @@ def __init__(self, size): self.size = size # elements stores the number of elements in the cache self.elements = 0 - + # helper function to add node to the double linked list (rear holds the most recently used node) def add(self, node): node.next = self.rear @@ -47,13 +48,13 @@ def remove(self, node): node.next.last = node.last node.next = None node.last = None - + # get: finds the value mapped to the key, returns None if key not present def get(self, key): # key not present - if (key not in self.cache): + if key not in self.cache: return None - + # the node pointed by the key is pushed to the end (most recently used) node = self.cache[key] self.remove(node) @@ -61,11 +62,11 @@ def get(self, key): # the value of the node is returned return node.val - + # set: takes a key value pair and stores them def set(self, key, val): # if the cache is full, the least recently used key value pair (at the head of the linked list) is deleted - if (self.size == self.elements): + if self.size == self.elements: node = self.head.next self.remove(node) self.elements -= 1 @@ -77,6 +78,7 @@ def set(self, key, val): self.elements += 1 self.cache[key] = node + # DRIVER CODE cache = LRU_Cache(3) diff --git a/Solutions/53.py b/Solutions/53.py index 10a852f..2c24c56 100644 --- a/Solutions/53.py +++ b/Solutions/53.py @@ -1,11 +1,11 @@ -''' +""" Problem: Implement a queue using two stacks. Recall that a queue is a FIFO (first-in, first-out) data structure with the following methods: * enqueue: which inserts an element into the queue * dequeue: which removes it. -''' +""" # local import from the DataStructure module from DataStructures.Stack import Stack @@ -22,21 +22,22 @@ def __sub__(self, other): temp = self.pop() # popping from the satck and pushing it to the other till the 1st stack is empty - while (temp != None): + while temp != None: other.push(temp) temp = self.pop() + # queue class using 2 stacks -class Queue(): +class Queue: # initalization with 2 stacks (stack1 is the main stack, stack2 is auxillary, its requried for dequeue operation) def __init__(self): self.stack1 = Stack_modified() self.stack2 = Stack_modified() - + # enqueue adds the passed value to the end of stack1 def enqueue(self, val): self.stack1.push(val) - + # dequeue opearation def dequeue(self): # storing the inverted stack1 in stack2 @@ -48,10 +49,11 @@ def dequeue(self): # returning the 1st inserted element return temp - + # string function to display the stack def __str__(self): - return ("Queue in Stack form:\n" + self.stack1.__str__()) + return "Queue in Stack form:\n" + self.stack1.__str__() + # DRIVER CODE queue = Queue() @@ -71,4 +73,4 @@ def __str__(self): print("De-Queued Element: {}".format(queue.dequeue())) print(queue) print("De-Queued Element: {}".format(queue.dequeue())) -print(queue) \ No newline at end of file +print(queue) diff --git a/Solutions/54.py b/Solutions/54.py index 153d1d4..a11374a 100644 --- a/Solutions/54.py +++ b/Solutions/54.py @@ -1,96 +1,100 @@ -''' +""" Problem: Sudoku is a puzzle where you're given a partially-filled 9 by 9 grid with digits. The objective is to fill the grid with the constraint that every row, column, and box (3 by 3 subgrid) must contain all of the digits from 1 to 9. Implement an efficient sudoku solver. -''' +""" # function to print a properly formatted board def print_board(board): # looping over the board for i in range(len(board)): # printing the subsection (row) - if (i % 3 == 0 and i != 0): + if i % 3 == 0 and i != 0: print("- - - - - - - - - - - -") # looping over the rows for j in range(len(board[0])): # printing the subsection (col) - if (j % 3 == 0 and j != 0): + if j % 3 == 0 and j != 0: print(" | ", end="") # displaying the elements ("." if the element is absent) - if (board[i][j] != 0): + if board[i][j] != 0: print(board[i][j], end=" ") else: print(".", end=" ") # breaking into a new line print() + # function to return the 1st empty element def find_empty(board): # traversing sequentially and searching for the 1st element containing 0 for i in range(len(board)): for j in range(len(board[0])): - if (board[i][j] == 0): + if board[i][j] == 0: return (i, j) # if the board is filled, None is returned return None + # function to check if a number can be placed without facing some confilct with another element def check(board, pos, num): # row check for i in range(len(board[0])): - if (board[pos[0]][i] == num): + if board[pos[0]][i] == num: return False - + # column check for i in range(len(board)): - if (board[i][pos[1]] == num): + if board[i][pos[1]] == num: return False - + # sub-section check sec_row = pos[0] // 3 sec_col = pos[1] // 3 # looping over the 3 rows in the sub-section - for i in range((sec_row*3), (sec_row*3)+3): + for i in range((sec_row * 3), (sec_row * 3) + 3): # looping over the 3 columns in the sub-section - for j in range((sec_col*3), (sec_col*3)+3): + for j in range((sec_col * 3), (sec_col * 3) + 3): # if the number is found, False is returned - if (board[i][j] == num): + if board[i][j] == num: return False - + # returning True if there is no confilct in any segment (row, col, sub-section) return True + # function to solve the sudoku board (recursive using backtracking) def sudoku_solver(board): # finding the 1st empty element loc = find_empty(board) # if the board is filled, True is returned - if (not loc): + if not loc: return True # trying to place 1 to 9 in the empty element, if successful, recursive call on board # if placement fails (due to conflict), backtracked to the last function call and modifying the value for i in range(1, 10): # checking placement with 1 to 9 - if (check(board, loc, i)): + if check(board, loc, i): board[loc[0]][loc[1]] = i # trying to solve for the next missing element - if (sudoku_solver(board)): + if sudoku_solver(board): return True - + # backtracking is placement was unsuccessful else: board[loc[0]][loc[1]] = 0 - + # returning False if the board cannot be solved return False + # DRIVER CODE board = [ [7, 8, 0, 4, 0, 0, 1, 2, 0], @@ -101,11 +105,11 @@ def sudoku_solver(board): [9, 0, 4, 0, 6, 0, 0, 0, 5], [0, 7, 0, 3, 0, 0, 0, 1, 2], [1, 2, 0, 0, 0, 7, 4, 0, 0], - [0, 4, 9, 2, 0, 6, 0, 0, 7] + [0, 4, 9, 2, 0, 6, 0, 0, 7], ] print("Initial Board:") print_board(board) sudoku_solver(board) print("\nFinal Board:") -print_board(board) \ No newline at end of file +print_board(board) diff --git a/Solutions/55.py b/Solutions/55.py index 2bff0fd..a8b61b2 100644 --- a/Solutions/55.py +++ b/Solutions/55.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement a URL shortener with the following methods: @@ -7,40 +7,41 @@ If no such shortened string exists, return null. Hint: What if we enter the same URL twice? -''' +""" # importing sha224 hash function from hashlib import sha224 # URL_Shortner class -class URL_Shortner(): +class URL_Shortner: # initialization function def __init__(self): # url_short: dictionary mapping the hash to the corresponding address # url_prefix: domain of the site self.url_short = {} self.url_prefix = "http://short_url.in/" - + # shorten function def shorten(self, url): # taking the 6 hex characters (48 out of the 224 characters) for short_url short_url = sha224(url.encode()).hexdigest()[:6] # if the hash doesn't contains a value, its stored in the dictionary - if (short_url not in self.url_short): + if short_url not in self.url_short: self.url_short[short_url] = url - + # returning the full shortened url (with domain) - return (self.url_prefix + short_url) - + return self.url_prefix + short_url + # restore function def restore(self, short): # if the shortened url is valid, the corresponding address is returned - if (short[-6:] in self.url_short): + if short[-6:] in self.url_short: return self.url_short[short[-6:]] # else None is returned return None + # DRIVER CODE us = URL_Shortner() @@ -49,4 +50,4 @@ def restore(self, short): print(short) print(us.restore(short)) -print(us.restore('http://short_url.in/64f827')) \ No newline at end of file +print(us.restore("http://short_url.in/64f827")) diff --git a/Solutions/56.py b/Solutions/56.py index 8665c9d..380688e 100644 --- a/Solutions/56.py +++ b/Solutions/56.py @@ -1,10 +1,10 @@ -''' +""" Problem: You are given an undirected graph represented as an adjacency matrix and an integer k. Write a function to determine whether each vertex in the graph can be colored such that no two adjacent vertices share the same color. You can use at most k colors. -''' +""" # FUNCTION TO PERFORM THE OPERATION def check_can_color(adjacency_matrix, k): @@ -19,16 +19,17 @@ def check_can_color(adjacency_matrix, k): # looping over all neighbors for j in range(len(adjacency_matrix[0])): # if i == j => there is a loop in the graph (its not considered), else temp is incremented - if (i != j): - if (adjacency_matrix[i][j] != 0): + if i != j: + if adjacency_matrix[i][j] != 0: temp += 1 - + # updating col_req as per requirement - if (temp > col_req): + if temp > col_req: col_req = temp # returns boolean (whether col_req is less than or equal to k) - return (col_req <= k) + return col_req <= k + # DRIVER CODE adjacency_matrix = [ @@ -39,4 +40,4 @@ def check_can_color(adjacency_matrix, k): ] print(check_can_color(adjacency_matrix, 4)) -print(check_can_color(adjacency_matrix, 3)) \ No newline at end of file +print(check_can_color(adjacency_matrix, 3)) diff --git a/Solutions/57.py b/Solutions/57.py index 7c1339e..e908481 100644 --- a/Solutions/57.py +++ b/Solutions/57.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a string s and an integer k, break up the string into multiple lines such that each line has a length of k or less. @@ -9,7 +9,7 @@ Example: "the quick brown fox jumps over the lazy dog", 10 => ["the quick", "brown fox", "jumps over", "the lazy", "dog"] -''' +""" # FUNCTION TO PERFORM THE OPERATION def break_string(string, k): @@ -27,19 +27,19 @@ def break_string(string, k): temp = len(i) # if the loop is just starting this conditional is entered - if (curr_len == 0): + if curr_len == 0: # if the word length is larger than k, None is returned, else curr_len and curr_str are updated - if (temp < k): + if temp < k: curr_len = temp curr_str = i else: return None # if the word length is larger than k, None is returned, else word_list, curr_len and curr_str are updated - elif (curr_len + temp + 1 > k): - if (temp > k): + elif curr_len + temp + 1 > k: + if temp > k: return None - + word_list.append(curr_str) curr_str = i curr_len = temp @@ -48,11 +48,12 @@ def break_string(string, k): else: curr_len += temp curr_str += " " + i - + # adding the final string and returning the word_list word_list.append(curr_str) return word_list + # DRIVER CODE print(break_string("the quick brown fox jumps over the lazy dog", 10)) -print(break_string("the quick brown fox jumps over the lazy dog", 3)) \ No newline at end of file +print(break_string("the quick brown fox jumps over the lazy dog", 3)) diff --git a/Solutions/58.py b/Solutions/58.py index e641e4a..dfc56b0 100644 --- a/Solutions/58.py +++ b/Solutions/58.py @@ -1,4 +1,4 @@ -''' +""" Problem: An sorted array of integers was rotated an unknown number of times. @@ -8,78 +8,81 @@ Example: [13, 18, 25, 2, 8, 10], 8 => 4 (the index of 8 in the array) -''' +""" # helper function to find the pivot position def find_pivot(arr, start, stop, length): # if the start and the stop pointers cross each other, the arr is sorted with no pivot # NOTE: This works only if we have a sorted and rotated array - if (stop < start): + if stop < start: return 0 - + # finding the middle of the array mid = (start + stop) // 2 - # checking the corresponding condition to detect where the pivot is + # checking the corresponding condition to detect where the pivot is # if mid value is larger than mid-1, the pivot is at the mid - if (mid > 0 and arr[mid-1] > arr[mid]): + if mid > 0 and arr[mid - 1] > arr[mid]: return mid # if the mid+1 value is smaller than the mid, the pivot is at the mid+1 - elif (mid < length-1 and arr[mid+1] < arr[mid]): - return mid+1 + elif mid < length - 1 and arr[mid + 1] < arr[mid]: + return mid + 1 # if the 1st element under consideration is smaller than the mid, the pivot is on the right - elif (arr[start] < arr[mid]): - return find_pivot(arr, mid+1, stop, length) + elif arr[start] < arr[mid]: + return find_pivot(arr, mid + 1, stop, length) # if the last element under consideration is larger than the mid, the pivot is on the left - elif (arr[stop] > arr[mid]): - return find_pivot(arr, start, mid-1, length) + elif arr[stop] > arr[mid]: + return find_pivot(arr, start, mid - 1, length) + # helper function to carry out binary search -def bin_search(arr, low, high, key): +def bin_search(arr, low, high, key): # checking if the high and low pointers crossed each other - if (high < low): + if high < low: return -1 - + # finding mid mid = (low + high) // 2 - + # if the key is at mid, mid is returned - if (key == arr[mid]): - return mid - + if key == arr[mid]: + return mid + # if key is larger than value at mid, bin_search is called on the right of mid - if (key > arr[mid]): + if key > arr[mid]: return bin_search(arr, (mid + 1), high, key) # else bin_search is called on the left of mid else: - return bin_search(arr, low, (mid -1), key) + return bin_search(arr, low, (mid - 1), key) + # FUNCTION TO PERFORM THE OPERATION def pivoted_bin_search(arr, length, element): # getting the pivot - pivot = find_pivot(arr, 0, length-1, length) + pivot = find_pivot(arr, 0, length - 1, length) # if the pivot is the searched element, pivot is returned - if (arr[pivot] == element): + if arr[pivot] == element: return pivot - + # if value at pivot is smaller than the element (value may exist), bin_search is called to the right of the pivot - if (arr[pivot] < element): - temp = bin_search(arr, pivot+1, length-1, element) + if arr[pivot] < element: + temp = bin_search(arr, pivot + 1, length - 1, element) # if the value is found, the location is returned - if (temp != -1): + if temp != -1: return temp # if the element is not present at the right, bin_search is called on the left else: - temp = bin_search(arr, 0, pivot-1, element) + temp = bin_search(arr, 0, pivot - 1, element) # if the value is found, the location is returned, else None is returned - if (temp != -1): + if temp != -1: return temp return None # if the value cannot be in the array (smaller than the smallest element), None is returned else: return None + # DRIVER CODE arr = [13, 18, 25, 2, 8, 10] print(pivoted_bin_search(arr, len(arr), 8)) @@ -90,4 +93,4 @@ def pivoted_bin_search(arr, length, element): arr = [25, 2, 8, 10, 13, 18] print(pivoted_bin_search(arr, len(arr), 8)) arr = [8, 10, 13, 18, 25, 2] -print(pivoted_bin_search(arr, len(arr), 8)) \ No newline at end of file +print(pivoted_bin_search(arr, len(arr), 8)) diff --git a/Solutions/59.py b/Solutions/59.py index 8047bf8..a62272f 100644 --- a/Solutions/59.py +++ b/Solutions/59.py @@ -1,9 +1,9 @@ -''' +""" Problem: Implement a file syncing algorithm for two computers over a low-bandwidth network. What if we know the files in the two computers are mostly the same? -''' +""" # library import from hashlib import sha256 @@ -17,7 +17,7 @@ class MerkleNode: def __init__(self): self.parent = None self.node_hash = None - + # add to directory function (used for both file and directory to add them as a sub-file/sub-directory) def add_to_directory(self, dir_node): # adding the node @@ -30,6 +30,7 @@ def add_to_directory(self, dir_node): dir_node.recalculate_hash() dir_node = dir_node.parent + # Merkle Directory class class MerkleDirectory(MerkleNode): # initialize function @@ -40,13 +41,13 @@ def __init__(self, name): self.is_dir = True self.name = name # creating a file on directory initialize and recalculating hash - new_file = MerkleFile('dir_init') + new_file = MerkleFile("dir_init") new_file.add_to_directory(self) # display functions (str and repr) def __str__(self): - return f'Name: {self.name}\nChildren: {self.children}' - + return f"Name: {self.name}\nChildren: {self.children}" + def __repr__(self): return "\n" + self.__str__() @@ -59,38 +60,39 @@ def recalculate_hash(self): cumulative_hash += child.node_hash self.node_hash = hash_func(cumulative_hash.encode()).hexdigest() else: - self.node_hash = hash_func(''.encode()).hexdigest() - + self.node_hash = hash_func("".encode()).hexdigest() + # function to synchronize 2 directories def sync(self, other): # if the directories have the same hash, they are already synchronized - if (self.node_hash == other.node_hash): + if self.node_hash == other.node_hash: return - + # copying from self to other for node in self.children: - if (not node in other.children): + if not node in other.children: (type(node))(other.children.add(node)) - + # copying from other to self for node in other.children: - if (not node in self.children): + if not node in self.children: (type(node))(self.children.add(node)) # NOTE: Type-casting is used to get a deep copy instead of a shallow one + # Merkle File class class MerkleFile(MerkleNode): # initialize function def __init__(self, name): MerkleNode.__init__(self) - self.node_contents = '' + self.node_contents = "" self.is_dir = False self.name = name self.node_hash = hash_func(self.node_contents.encode()).hexdigest() - + # display functions (repr) def __repr__(self): - return f'\nName: {self.name}\nContent: {self.node_contents}' + return f"\nName: {self.name}\nContent: {self.node_contents}" # function to update the contents of the file def update_contents(self, new_contents): @@ -100,19 +102,21 @@ def update_contents(self, new_contents): if self.parent: self.parent.recalculate_hash() + # Computer class -class Computer(): +class Computer: # initialize function def __init__(self): - self.root = MerkleDirectory('root') - + self.root = MerkleDirectory("root") + # synchronize function def sync(self, new_comp): - if (type(new_comp) == Computer): + if type(new_comp) == Computer: print("Syncing computers...") self.root.sync(new_comp.root) print("Sync successful!\n") + # DRIVER CODE c1 = Computer() c2 = Computer() @@ -123,11 +127,11 @@ def sync(self, new_comp): print(c2.root) print() -new_file = MerkleFile('check_file') -new_file.update_contents('Check') +new_file = MerkleFile("check_file") +new_file.update_contents("Check") new_file.add_to_directory(c1.root) -new_dir = MerkleDirectory('check_dir') +new_dir = MerkleDirectory("check_dir") new_dir.add_to_directory(c2.root) print("COMPUTER 1:") @@ -144,11 +148,11 @@ def sync(self, new_comp): print(c2.root) print() -new_file = MerkleFile('check_file2') -new_file.update_contents('Check Again') +new_file = MerkleFile("check_file2") +new_file.update_contents("Check Again") new_file.add_to_directory(c1.root) print("COMPUTER 1:") print(c1.root) print("COMPUTER 2:") -print(c2.root) \ No newline at end of file +print(c2.root) diff --git a/Solutions/60.py b/Solutions/60.py index d01e05d..e81edf5 100644 --- a/Solutions/60.py +++ b/Solutions/60.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a multiset of integers, return whether it can be partitioned into two subsets whose sums are the same. @@ -6,34 +6,39 @@ Example: [15, 5, 20, 10, 35, 15, 10] => true (since we can split it up into {15, 5, 10, 15, 10} and {20, 35}, which both add up to 55) [15, 5, 20, 10, 35] => false -''' +""" # helper function to check for checking whether splitting into 2 subsets of equal sum is possible def split_helper(arr, start, stop, sum_inner, sum_outer): # if the start and the stop pointers cross each other, the list cannot be split - if (start >= stop): + if start >= stop: return False # if (sum_inner = sum_outer), we have found the split - elif (sum_inner == sum_outer): + elif sum_inner == sum_outer: return True - + # checking for possible splits (once with adding 1st element to sum_outer, again with last element, giving rise to a recursion tree) - return (split_helper(arr, start+1, stop, sum_inner-arr[start], sum_outer+arr[start]) or \ - split_helper(arr, start, stop-1, sum_inner-arr[stop], sum_outer+arr[stop])) + return split_helper( + arr, start + 1, stop, sum_inner - arr[start], sum_outer + arr[start] + ) or split_helper( + arr, start, stop - 1, sum_inner - arr[stop], sum_outer + arr[stop] + ) + # FUNCTION FOR PERFORMING THE OPERATION def equal_sum_split_check(arr): - # checking if the sum is odd (it cannot be split) + # checking if the sum is odd (it cannot be split) # [even though theoretically, empty set can be broken into 2 empty sets, we have condidered the case for valid elements] - if (not arr or sum(arr) % 2 == 1): + if not arr or sum(arr) % 2 == 1: return False - + # sorting the list (pre-requisite for split_helper) arr.sort() # returning the value returned by split_helper - return split_helper(arr, 0, len(arr)-1, sum(arr), 0) + return split_helper(arr, 0, len(arr) - 1, sum(arr), 0) + # DRIVER CODE print(equal_sum_split_check([15, 5, 20, 10, 35, 15, 10])) -print(equal_sum_split_check([15, 5, 20, 10, 35])) \ No newline at end of file +print(equal_sum_split_check([15, 5, 20, 10, 35])) diff --git a/Solutions/61.py b/Solutions/61.py index 01ec15c..aaccf8a 100644 --- a/Solutions/61.py +++ b/Solutions/61.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement integer exponentiation. That is, implement the pow(x, y) function, where x and y are integers and returns x^y. @@ -6,21 +6,22 @@ Example: 2, 10 => 1024 -''' +""" # FUNCTION TO PERFORM THE OPERATION def pow(base, power): # this function implements a method similar to binary search, the effective complexity is O(log(n)) # base case [x^0 = 1] - if (power == 0): + if power == 0: return 1 # if the exponent is odd, the result is given by [base ^ exp = ((base * base) ^ floor(exp / 2)) * base] - elif (power % 2 != 0): - return (pow((base*base), power//2) * base) + elif power % 2 != 0: + return pow((base * base), power // 2) * base # if the exponent is even, the result is given by [base ^ exp = (base * base) ^ floor(exp / 2)] else: - return pow((base*base), power//2) + return pow((base * base), power // 2) + # DRIVER CODE print(pow(2, 10)) -print(pow(3, 4)) \ No newline at end of file +print(pow(3, 4)) diff --git a/Solutions/62.py b/Solutions/62.py index d8cccb1..dc58637 100644 --- a/Solutions/62.py +++ b/Solutions/62.py @@ -1,4 +1,4 @@ -''' +""" Problem: There is an N by M matrix of zeroes. @@ -12,7 +12,7 @@ * Down, then right) 5, 5 => 70 -''' +""" # FUNCTION TO PERFORM THE OPERATION def num_ways(n, m): @@ -24,11 +24,12 @@ def num_ways(n, m): # the values are populated from top left to bottom right for i in range(1, n): for j in range(1, m): - mat[i][j] = mat[i-1][j] + mat[i][j-1] - + mat[i][j] = mat[i - 1][j] + mat[i][j - 1] + # the final result is at the mat[n-1][m-1] - return mat[n-1][m-1] + return mat[n - 1][m - 1] + # DRIVER CODE print(num_ways(2, 2)) -print(num_ways(5, 5)) \ No newline at end of file +print(num_ways(5, 5)) diff --git a/Solutions/63.py b/Solutions/63.py index f7973b0..4ee5116 100644 --- a/Solutions/63.py +++ b/Solutions/63.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given a 2D matrix of characters and a target word. @@ -12,7 +12,7 @@ ['M', 'A', 'S', 'S']] 'FOAM' => true (since it's the leftmost column) 'MASS' => true (since it's the last row) -''' +""" # FUNCTION TO PERFORM THE OPERATION def word_occorance_check(mat, word): @@ -22,28 +22,31 @@ def word_occorance_check(mat, word): # row check (searching for the word in every row) for i in range(n): - temp = ''.join(mat[i]) + temp = "".join(mat[i]) - if (word in temp): + if word in temp: return True - + # column check (searching for the word in every column) for j in range(m): - temp = '' + temp = "" for i in range(n): temp += mat[i][j] - - if (word in temp): + + if word in temp: return True - + return False + # DRIVER CODE -mat = [['F', 'A', 'C', 'I'], - ['O', 'B', 'Q', 'P'], - ['A', 'N', 'O', 'B'], - ['M', 'A', 'S', 'S']] +mat = [ + ["F", "A", "C", "I"], + ["O", "B", "Q", "P"], + ["A", "N", "O", "B"], + ["M", "A", "S", "S"], +] print(word_occorance_check(mat, "FOAM")) print(word_occorance_check(mat, "MASS")) -print(word_occorance_check(mat, "FORM")) \ No newline at end of file +print(word_occorance_check(mat, "FORM")) diff --git a/Solutions/64.py b/Solutions/64.py index 96d8010..bfd758c 100644 --- a/Solutions/64.py +++ b/Solutions/64.py @@ -1,9 +1,9 @@ -''' +""" Problem: A knight's tour is a sequence of moves by a knight on a chessboard such that all squares are visited once. Given N, write a function to return the number of knight's tours on an N by N chessboard. -''' +""" # global variable count COUNT = 0 @@ -15,14 +15,14 @@ def get_valid_pos(pos, n): # getting all the next moves pos_arr = [ - (y+1, x+2), - (y-1, x+2), - (y+1, x-2), - (y-1, x-2), - (y+2, x+1), - (y+2, x-1), - (y-2, x+1), - (y-2, x-1) + (y + 1, x + 2), + (y - 1, x + 2), + (y + 1, x - 2), + (y - 1, x - 2), + (y + 2, x + 1), + (y + 2, x - 1), + (y - 2, x + 1), + (y - 2, x - 1), ] # res: stores the permissible moves @@ -32,14 +32,15 @@ def get_valid_pos(pos, n): for i in range(8): # breaking the position into x_test and y_test y_test, x_test = pos_arr[i] - + # adding the valid moves to res if not (y_test >= n or x_test >= n or x_test < 0 or y_test < 0): res.append(pos_arr[i]) - + # returning the valid moves return res + # helper function to check if all locations have been visited def complete_check(board): # traversing each row @@ -47,11 +48,12 @@ def complete_check(board): # traversing each element for elem in row: # if the element=0 (not visited), False is returned - if (elem == 0): + if elem == 0: return False # if no unvisited element is found, True is returned return True + # helper function to solve the problem (does the actual processing) def solver_helper(board, pos): # declaring COUNT as a global variable @@ -59,38 +61,39 @@ def solver_helper(board, pos): # if the board is complete, count is incremented and None returned [backtracked and resolved] # (as all combinations has to be check: we need the number of possible solutions, not the solution) - if (complete_check(board)): + if complete_check(board): COUNT += 1 return - + # looping over the valid positions for valid_pos in get_valid_pos(pos, len(board)): # breaking the pos into x and y y, x = valid_pos # if the position has not been visited in the current path, its processed - if (board[y][x] == 0): + if board[y][x] == 0: # marking the position as visited board[y][x] = 1 # recursively calling the function to solve for the other positions solver_helper(board, valid_pos) # backtracking and resolving the board board[y][x] = 0 - + return + # FUNCTION TO SOLVE THE PROBLEM def solve(n): # declaring COUNT as a global variable global COUNT - + # creating the board using list comprehension board = [[0 for i in range(n)] for j in range(n)] # setting the initial position of the knight board[0][0] = 1 # calling the helper function to solve the problem - solver_helper(board, (0,0)) + solver_helper(board, (0, 0)) # keeping the value of COUNT in temp and reseting COUNT temp = COUNT @@ -99,9 +102,10 @@ def solve(n): # returning temp return temp + # DRIVER CODE print(solve(1)) print(solve(2)) print(solve(3)) print(solve(4)) -print(solve(5)) \ No newline at end of file +print(solve(5)) diff --git a/Solutions/65.py b/Solutions/65.py index 97efa8f..9504b2b 100644 --- a/Solutions/65.py +++ b/Solutions/65.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a N by M matrix of numbers, print out the matrix in a clockwise spiral. @@ -28,7 +28,7 @@ 14 13 12 -''' +""" # unwind helper function to get the current ring def unwind_mat_helper(mat, ring, n, m): @@ -36,75 +36,66 @@ def unwind_mat_helper(mat, ring, n, m): ring_arr = [] # getting the 1st row - for i in range(ring, m-ring): + for i in range(ring, m - ring): ring_arr.append(mat[ring][i]) - + # getting the last column - for i in range(ring+1, n-ring): - ring_arr.append(mat[i][m-ring-1]) + for i in range(ring + 1, n - ring): + ring_arr.append(mat[i][m - ring - 1]) # getting the last row (if it exists) - if (n > 1 and m > 1): - for i in range(m-ring-2, ring-1, -1): - ring_arr.append(mat[n-ring-1][i]) + if n > 1 and m > 1: + for i in range(m - ring - 2, ring - 1, -1): + ring_arr.append(mat[n - ring - 1][i]) # getting the last column (if it exists) - if (n > 1 and m > 1): - for i in range(n-ring-2, ring, -1): + if n > 1 and m > 1: + for i in range(n - ring - 2, ring, -1): ring_arr.append(mat[i][ring]) - + return ring_arr + # FUNCTION TO PERFORM THE OPERATION def unwind_mat(mat, n, m): # res stores the list of unwinded matrix elements res = [] # if (there is more than 1 row/col) - if (n > 1 and m > 1): + if n > 1 and m > 1: # the number of rings will be (max(n, m)//2) # res is extended by the ring as per the number of iterations - for i in range(max(n, m)//2): + for i in range(max(n, m) // 2): res.extend(unwind_mat_helper(mat, i, n, m)) - + # if there is 1 row or column, only 1 ring is present else: res = unwind_mat_helper(mat, 0, n, m) - + return res + # DRIVER CODE -mat = [[1, 2, 3, 4, 5], - [6, 7, 8, 9, 10], - [11, 12, 13, 14, 15], - [16, 17, 18, 19, 20]] +mat = [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15], [16, 17, 18, 19, 20]] for i in unwind_mat(mat, len(mat), len(mat[0])): print(i) print() -mat = [[1, 2, 3], - [4, 5, 6]] +mat = [[1, 2, 3], [4, 5, 6]] for i in unwind_mat(mat, len(mat), len(mat[0])): print(i) print() -mat = [[1, 4], - [2, 5], - [3, 6]] +mat = [[1, 4], [2, 5], [3, 6]] for i in unwind_mat(mat, len(mat), len(mat[0])): print(i) print() -mat = [[1], - [2], - [3], - [4], - [5], - [6]] +mat = [[1], [2], [3], [4], [5], [6]] for i in unwind_mat(mat, len(mat), len(mat[0])): print(i) print() mat = [[1, 2, 3]] for i in unwind_mat(mat, len(mat), len(mat[0])): - print(i) \ No newline at end of file + print(i) diff --git a/Solutions/66.py b/Solutions/66.py index ad20a1c..acee35d 100644 --- a/Solutions/66.py +++ b/Solutions/66.py @@ -1,10 +1,10 @@ -''' +""" Problem: Assume you have access to a function toss_biased() which returns 0 or 1 with a probability that's not 50-50 (but also not 0-100 or 100-0). You do not know the bias of the coin. Write a function to simulate an unbiased coin toss. -''' +""" # library imports # matplotlib is not mandatory, its used to plot the distribution of results @@ -17,11 +17,12 @@ def toss_biased(): temp = randint(1, 100) # if the number is less than 30, 0 is returned else 1 (30-70 bias) - if (temp < 30): + if temp < 30: return 0 else: return 1 + # unbiased toss function def toss_unbiased(): # getting the biased toss value twice @@ -29,23 +30,24 @@ def toss_unbiased(): temp2 = toss_biased() # as long as we dont get different values, we keep tossing - while (temp1 == temp2): + while temp1 == temp2: temp1 = toss_biased() temp2 = toss_biased() - + # when different values are achieved, any 1 can be returned (here the 1st one is returned) return temp1 + # DRIVER CODE biased = [toss_biased() for i in range(100000)] unbiased = [toss_unbiased() for i in range(100000)] # displaying biased distribution -plt.title('Biased Distribution') +plt.title("Biased Distribution") plt.hist(biased, bins=2, edgecolor="black") plt.show() # displaying unbiased distribution -plt.title('Unbiased Distribution') +plt.title("Unbiased Distribution") plt.hist(unbiased, bins=2, edgecolor="black") -plt.show() \ No newline at end of file +plt.show() diff --git a/Solutions/67.py b/Solutions/67.py index 93dcd45..12edf2c 100644 --- a/Solutions/67.py +++ b/Solutions/67.py @@ -1,4 +1,4 @@ -''' +""" Problem: Implement an LFU (Least Frequently Used) cache. @@ -10,10 +10,10 @@ * get(key): gets the value at key. If no such key exists, return null. Each operation should run in O(1) time. -''' +""" # node class for the double linked list (in LFU Cache) -class Node(): +class Node: # initalize method def __init__(self, key, val): self.key = key @@ -21,13 +21,14 @@ def __init__(self, key, val): self.freq = 1 self.last = None self.next = None - + # bollean method def __bool__(self): return bool(self.key) + # LFU Cache -class LFU_Cache(): +class LFU_Cache: # initalize method def __init__(self, size): self.head = Node(None, None) @@ -37,7 +38,7 @@ def __init__(self, size): self.cache = {} self.size = size self.elements = 0 - + # helper method to add a node to the proper position in the cache linked list def add(self, node): # inserting the node at head.next @@ -51,7 +52,7 @@ def add(self, node): # helper function to move the node to the proper position based on the frequency def move_to_pos(self, node): - while (node.next and node.next.freq <= node.freq): + while node.next and node.next.freq <= node.freq: node1 = node node2 = node.next @@ -70,25 +71,25 @@ def remove(self, node): node.next.last = node.last node.next = None node.last = None - + # FUNCTION TO PERFORM THE OPERATION (get) def get(self, key): # if the key doesn't exist, None is returned - if (key not in self.cache): + if key not in self.cache: return None - + # incrementing the freq of the accessed node node = self.cache[key] node.freq += 1 # moving the node at the proper position based on the frequency of use self.move_to_pos(node) - + return node.val - + # FUNCTION TO PERFORM THE OPERATION (set) def set(self, key, val): # if the number of elements has reached the max size, the least used element is deleted - if (self.size == self.elements): + if self.size == self.elements: node = self.head.next self.remove(node) self.elements -= 1 @@ -100,6 +101,7 @@ def set(self, key, val): self.elements += 1 self.cache[key] = node + # DRIVER CODE cache = LFU_Cache(3) diff --git a/Solutions/68.py b/Solutions/68.py index c6775d7..5e06e9a 100644 --- a/Solutions/68.py +++ b/Solutions/68.py @@ -1,4 +1,4 @@ -''' +""" Problem: On our special chessboard, two bishops attack each other if they share the same diagonal. @@ -17,7 +17,7 @@ [0 0 0 0 0] [b 0 0 0 0]> Output = 2 (since bishops 1 and 3 attack each other, as well as bishops 3 and 4) -''' +""" # helper function to calculate the diagonals def get_diagonal_pos(pos, board_size): @@ -31,48 +31,49 @@ def get_diagonal_pos(pos, board_size): curr_row = row - 1 curr_col = col - 1 for _ in range(board_size): - if (curr_col < 0 or curr_row < 0): + if curr_col < 0 or curr_row < 0: break diagonals.add((curr_row, curr_col)) curr_row -= 1 curr_col -= 1 - + # calculating the lower right diagonal positions curr_row = row + 1 curr_col = col + 1 for _ in range(board_size): - if (curr_col >= board_size or curr_row >= board_size): + if curr_col >= board_size or curr_row >= board_size: break diagonals.add((curr_row, curr_col)) curr_row += 1 curr_col += 1 - + # calculating the upper right diagonal positions curr_row = row - 1 curr_col = col + 1 for _ in range(board_size): - if (curr_col >= board_size or curr_row < 0): + if curr_col >= board_size or curr_row < 0: break diagonals.add((curr_row, curr_col)) curr_row -= 1 curr_col += 1 - + # calculating the lower left diagonal positions curr_row = row + 1 curr_col = col - 1 for _ in range(board_size): - if (curr_col < 0 or curr_row >= board_size): + if curr_col < 0 or curr_row >= board_size: break diagonals.add((curr_row, curr_col)) curr_row += 1 curr_col -= 1 - + return diagonals + # FUNCTION TO PERFORM THE OPERATION def num_attacking(board_size, pos_list): # count stores the number of attacking bishops @@ -87,17 +88,13 @@ def num_attacking(board_size, pos_list): for pos in pos_list: # if there is a bishop in the diagonal, count is incremented # it considers odering (so (1, 2) and (2, 1) are considered different) - if (pos in diagonals): + if pos in diagonals: count += 1 - + # to eliminate ordering problem, (count/2) is returned - return (count // 2) + return count // 2 + # DRIVER CODE -pos_list = [ - (0, 0), - (1, 2), - (2, 2), - (4, 0) -] -print(num_attacking(5, pos_list)) \ No newline at end of file +pos_list = [(0, 0), (1, 2), (2, 2), (4, 0)] +print(num_attacking(5, pos_list)) diff --git a/Solutions/69.py b/Solutions/69.py index dd936d4..a265768 100644 --- a/Solutions/69.py +++ b/Solutions/69.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of integers, return the largest product that can be made by multiplying any three integers. @@ -8,7 +8,7 @@ Input = [-10, -10, 5, 2] Output = 500 (-10 * -10 * 5) -''' +""" # FUNCTION TO PERFORM THE OPERATION def largest_prod_3(Arr, length): @@ -23,36 +23,37 @@ def largest_prod_3(Arr, length): # looping over the array for i in range(length): # if the current element is smaller than neg1, neg1 & neg2 are updated - if (Arr[i] < neg1): + if Arr[i] < neg1: neg2 = neg1 neg1 = Arr[i] - + # if the current element is smaller than neg2 and larger than neg1, neg2 are updated - elif (Arr[i] < neg2): + elif Arr[i] < neg2: neg2 = Arr[i] - + # if the current element is larger than pos1, pos1, pos2 & pos3 are updated - elif (Arr[i] > pos1): + elif Arr[i] > pos1: pos3 = pos2 pos2 = pos1 pos1 = Arr[i] - + # if the current element is larger than pos2 and smaller than pos1, pos2 & pos3 are updated - elif (Arr[i] > pos2): + elif Arr[i] > pos2: pos3 = pos2 pos2 = Arr[i] - + # if the current element is larger than pos3 and smaller than pos2, pos3 is updated - elif (Arr[i] > pos2): + elif Arr[i] > pos2: pos3 = Arr[i] - + # the product of neg1 & neg2 is larger than that of pos2 & pos3, then they are multiplied in the final product # else pos2 & pos3 are multiplied in the final product - if ((neg1 * neg2) > (pos2 * pos3)): - return (neg2 * neg1 * pos1) + if (neg1 * neg2) > (pos2 * pos3): + return neg2 * neg1 * pos1 else: - return (pos1 * pos2 * pos3) + return pos1 * pos2 * pos3 + # DRIVER CODE inp = [-10, -10, 5, 2] -print(largest_prod_3(inp, len(inp))) \ No newline at end of file +print(largest_prod_3(inp, len(inp))) diff --git a/Solutions/70.py b/Solutions/70.py index 750016b..c374e5f 100644 --- a/Solutions/70.py +++ b/Solutions/70.py @@ -1,4 +1,4 @@ -''' +""" Problem: A number is considered perfect if its digits sum up to exactly 10. @@ -11,7 +11,7 @@ Input = 2 Output = 28 -''' +""" # NOTE: I found several methods to perform the operation, but none of them work properly as the number grows larger # Only the naive approach works properly for all numbers (but its painfully slow) @@ -21,20 +21,22 @@ # my approach to solve the problem def nth_perfect_num_mine(n): - num = 19 + (9 * (n-1)) + num = 19 + (9 * (n - 1)) outliers = n // 10 - num += (9 * outliers) + num += 9 * outliers return num + # method 1 to solve the problem def nth_perfect_num_1(n): - num = 19 + (9 * (n-1)) + num = 19 + (9 * (n - 1)) outliers = int(log10(num)) - 1 - num += (9 * outliers) + num += 9 * outliers return num + # method 2 to solve the problem def nth_perfect_num_2(n): tmp_sum = 0 @@ -43,6 +45,7 @@ def nth_perfect_num_2(n): return (n * 10) + (10 - tmp_sum) + # function to calculate the sum of the digits of a number (takes string as input as its easier to parse) def calc_sum(num): s = 0 @@ -50,6 +53,7 @@ def calc_sum(num): s += int(i) return s + # naive approach to solve the problem def nth_perfect_num_naive(n): # starting with default value of 19 for number & 1 for count @@ -57,45 +61,46 @@ def nth_perfect_num_naive(n): count = 1 # looping till we find n perfect numbers - while (n > count): + while n > count: # incrementing num (to get the next number) num += 1 # if the number is perfect, count is incremented - if (calc_sum(str(num)) == 10): + if calc_sum(str(num)) == 10: count += 1 - + # finally the number is returned on loop termination return num + # displaying the error percent for my method count = 0 for i in range(1, 500): num = calc_sum(str(nth_perfect_num_mine(i))) - if (num != 10): + if num != 10: count += 1 -print('Errors (my method):\t[', count, ']', (count / 5), '%') +print("Errors (my method):\t[", count, "]", (count / 5), "%") # displaying the error percent for method 1 count = 0 for i in range(1, 500): num = calc_sum(str(nth_perfect_num_1(i))) - if (num != 10): + if num != 10: count += 1 -print('Errors (method 1):\t[', count, ']', (count / 5), '%') +print("Errors (method 1):\t[", count, "]", (count / 5), "%") # displaying the error percent for method 2 count = 0 for i in range(1, 500): num = calc_sum(str(nth_perfect_num_2(i))) - if (num != 10): + if num != 10: count += 1 -print('Errors (method 2):\t[', count, ']', (count / 5), '%') +print("Errors (method 2):\t[", count, "]", (count / 5), "%") # displaying the error percent for method naive count = 0 for i in range(1, 500): num = calc_sum(str(nth_perfect_num_naive(i))) - if (num != 10): + if num != 10: count += 1 -print('Errors (naive): \t[', count, ']', (count / 5), '%') +print("Errors (naive): \t[", count, "]", (count / 5), "%") diff --git a/Solutions/71.py b/Solutions/71.py index 1bebd9d..f9b2860 100644 --- a/Solutions/71.py +++ b/Solutions/71.py @@ -1,9 +1,9 @@ -''' +""" Problem: You have a function rand7() that returns an integer from 1 to 7 (inclusive) with uniform probability. Implement a function rand5() that returns an integer from 1 to 5 (inclusive). -''' +""" # library imports (pyplot is not mandatory, its used to plot the distribution) from random import randint @@ -13,21 +13,23 @@ def rand7(): return randint(1, 7) + # rand5 function def rand5(): # generating a random number between 1 to 7 val = rand7() # if the generated number is in the range [1, 5], its returned - if (val <= 5): + if val <= 5: return val # if the number is outside the range, rand5 is called again recursively return rand5() + # code to plot the distribution by generating 10000 numbers res = [] for i in range(10000): res.append(rand5()) -plt.hist(res, bins=5, edgecolor='black') -plt.show() \ No newline at end of file +plt.hist(res, bins=5, edgecolor="black") +plt.show() diff --git a/Solutions/72.py b/Solutions/72.py index b92d4cc..cc8f031 100644 --- a/Solutions/72.py +++ b/Solutions/72.py @@ -1,4 +1,4 @@ -''' +""" Problem: In a directed graph, each node is assigned an uppercase letter. @@ -22,9 +22,10 @@ Input = A, [(0, 0)] Output = None (since we have an infinite loop) -''' +""" # NOTE: I didn't write this code, but it solves the problem in an efficient way + class GraphPath: def __init__(self, nodes=set(), letter_counts=dict()): self.nodes = nodes @@ -52,8 +53,7 @@ def get_max_value_string(graph_path, node, adjacency_map): paths = list() for child_node in adjacency_map[node]: - new_paths = get_max_value_string( - new_graph_path, child_node, adjacency_map) + new_paths = get_max_value_string(new_graph_path, child_node, adjacency_map) paths.extend(new_paths) return paths @@ -90,6 +90,7 @@ def get_max_value_string_helper(graph_string, edge_list): return max_value if max_value > 0 else None + # DRIVER CODE print(get_max_value_string_helper("ABACA", [(0, 1), (0, 2), (2, 3), (3, 4)])) -print(get_max_value_string_helper("A", [(0, 0)])) \ No newline at end of file +print(get_max_value_string_helper("A", [(0, 0)])) diff --git a/Solutions/73.py b/Solutions/73.py index 30ae594..d13e3b1 100644 --- a/Solutions/73.py +++ b/Solutions/73.py @@ -1,8 +1,8 @@ -''' +""" Problem: Given the head of a singly linked list, reverse it in-place. -''' +""" # importing the linked list from DataStructures.LinkedList import Linked_list @@ -18,20 +18,21 @@ def reverse_inplace(LL): ptr3 = LL.head.next # looping over till we reach the end of the linked list - while (ptr2 != None): + while ptr2 != None: # reversing the flow (ptr2 -> ptr1) ptr2.next = ptr1 # updating the pointers to their next locations ptr1 = ptr2 ptr2 = ptr3 - if (ptr3 == None): + if ptr3 == None: break ptr3 = ptr3.next - + # setting the head of the linked list LL.head = ptr1 + # DRIVER CODE LL = Linked_list() @@ -48,4 +49,4 @@ def reverse_inplace(LL): reverse_inplace(LL) -print(LL) \ No newline at end of file +print(LL) diff --git a/Solutions/74.py b/Solutions/74.py index 44b5fde..1e02491 100644 --- a/Solutions/74.py +++ b/Solutions/74.py @@ -1,4 +1,4 @@ -''' +""" Problem 74: Suppose you have a multiplication table that is N by N. @@ -16,7 +16,7 @@ 5 10 15 20 25 30 6 12 18 24 30 36 And there are 4 12's in the table) -''' +""" # FUNCTION TO PERFORM THE OPERATION def freq_calc(n, x): @@ -24,22 +24,23 @@ def freq_calc(n, x): count = 0 # looping from 1 to n - for i in range(1, n+1): + for i in range(1, n + 1): # looping from 1 to i - for j in range(1, i+1): + for j in range(1, i + 1): # if the product is eual to x, the value of count has to be increased - if (i * j == x): + if i * j == x: # if the value of i and j are same (i * i = x, it will be considered once) - if (i == j): + if i == j: count += 1 # if the value of i and j are different (i * j = x implies j * i = x, it will be considered twice) else: count += 2 - + return count + # DRIVER CODE print(freq_calc(6, 12)) print(freq_calc(1, 1)) print(freq_calc(2, 4)) -print(freq_calc(3, 6)) \ No newline at end of file +print(freq_calc(3, 6)) diff --git a/Solutions/75.py b/Solutions/75.py index e0f83b3..f381801 100644 --- a/Solutions/75.py +++ b/Solutions/75.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of numbers, find the length of the longest increasing subsequence in the array. @@ -8,7 +8,7 @@ Input = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15] Output = 6 (the subsequence is [0, 2, 6, 9, 11, 15]) -''' +""" # FUNCTION TO PERFORM THE OPERATION def longest_increasing_subsequence(arr, length): @@ -21,13 +21,14 @@ def longest_increasing_subsequence(arr, length): for j in range(i): # if the element at current pos is larger than the one at j'th pos # (implying its an increasing subsequence) - if (arr[i] > arr[j]): + if arr[i] > arr[j]: # the value used for dynamic programming is updated # (max(arr_dp[i] (already a part of a larger sub-seq), arr_dp[j]+1 (the resultant sub-seq formed by extending from the j'th pos))) - arr_dp[i] = max(arr_dp[i], arr_dp[j]+1) - + arr_dp[i] = max(arr_dp[i], arr_dp[j] + 1) + return max(arr_dp) + # DRIVER CODE arr = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15] -print(longest_increasing_subsequence(arr, len(arr))) \ No newline at end of file +print(longest_increasing_subsequence(arr, len(arr))) diff --git a/Solutions/76.py b/Solutions/76.py index 91952dd..ccaa6f7 100644 --- a/Solutions/76.py +++ b/Solutions/76.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given an N by M 2D matrix of lowercase letters. @@ -16,7 +16,7 @@ Input = ['zyx', 'wvu', 'tsr'] Output = 3 (since we would need to remove all the columns to order it) -''' +""" # FUNCTION TO PERFORM THE OPERATION def calc(mat): @@ -30,14 +30,15 @@ def calc(mat): # looping over wach column for i in range(length): # checking if the columns are lexicographically arranged - for j in range(num_elements-1): + for j in range(num_elements - 1): # if the column is not lexicographical, count is incremented and control breaks out of the loop - if (mat[j][i] > mat[j+1][i]): + if mat[j][i] > mat[j + 1][i]: count += 1 break - + return count + # DRIVER CODE inp1 = ["cba", "daf", "ghi"] inp2 = ["abcdef"] @@ -45,4 +46,4 @@ def calc(mat): print(calc(inp1)) print(calc(inp2)) -print(calc(inp3)) \ No newline at end of file +print(calc(inp3)) diff --git a/Solutions/77.py b/Solutions/77.py index 41ad558..8f45c68 100644 --- a/Solutions/77.py +++ b/Solutions/77.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a list of possibly overlapping intervals, return a new list of intervals where all overlapping intervals have been merged. @@ -8,7 +8,7 @@ Input = [(1, 3), (5, 8), (4, 10), (20, 25)] Output = [(1, 3), (4, 10), (20, 25)] -''' +""" # FUNCTION TO PERFORM THE OPERATION def merge(intervals): @@ -25,19 +25,20 @@ def merge(intervals): for interval in intervals[1:]: # if the current end time is less than the next start time (no overlap) # the start (current) and end is added to the result and start/end reset - if (end < interval[0]): + if end < interval[0]: res.append((start, end)) start = interval[0] end = interval[1] # if the end lies between the next start and end, end is updated to next end - elif (end < interval[1] and end > interval[0]): + elif end < interval[1] and end > interval[0]: end = interval[1] - + # adding the last start and end pair res.append((start, end)) return res + # DRIVER CODE print(merge([(1, 3), (5, 8), (4, 10), (20, 25)])) -print(merge([(1, 3), (5, 10), (4, 8), (20, 25)])) \ No newline at end of file +print(merge([(1, 3), (5, 10), (4, 8), (20, 25)])) diff --git a/Solutions/78.py b/Solutions/78.py index 3b92e0d..ba276bd 100644 --- a/Solutions/78.py +++ b/Solutions/78.py @@ -1,8 +1,8 @@ -''' +""" Problem: Given k sorted singly linked lists, write a function to merge all the lists into one sorted singly linked list. -''' +""" # importing LinkedList from the DataStructures from DataStructures.LinkedList import Linked_list @@ -22,8 +22,8 @@ def merge_sorted_linked_list(list_of_LL, k): # looping over the position pointers for i in range(k): # if the pointer is not None and the value is less than the minimum, position & minimum is updated - if (pos[i] != None): - if (pos[i].val < minimum): + if pos[i] != None: + if pos[i].val < minimum: minimum = pos[i].val position = i @@ -31,9 +31,10 @@ def merge_sorted_linked_list(list_of_LL, k): sorted_list.add(pos[position].val) # the position pointer is moved to the next value pos[position] = pos[position].next - + return sorted_list + # DRIVER CODE LL1 = Linked_list() LL1.add(2) @@ -57,4 +58,4 @@ def merge_sorted_linked_list(list_of_LL, k): print(LL3) List = [LL1, LL2, LL3] -print(merge_sorted_linked_list(List, len(List))) \ No newline at end of file +print(merge_sorted_linked_list(List, len(List))) diff --git a/Solutions/79.py b/Solutions/79.py index 938836c..c0120cb 100644 --- a/Solutions/79.py +++ b/Solutions/79.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an array of integers, write a function to determine whether the array could become non-decreasing by modifying at most 1 element. @@ -7,7 +7,7 @@ [10, 5, 7] => true (since we can modify the 10 into a 1 to make the array non-decreasing) [10, 5, 1]=> false (since we can't modify any one element to get a non-decreasing array) -''' +""" # FUNCTION TO PERFORM THE OPERATION def check_1_modify_to_sorted(arr): @@ -19,18 +19,19 @@ def check_1_modify_to_sorted(arr): # iterating the list from the 2nd element for elem in arr[1:]: # if the difference is negative (next_elem - current_elem), neg_count is incremented - if ((elem - val) < 0): + if (elem - val) < 0: neg_count += 1 # if there is more than 1 element with negative difference, the list cannot be made ascending by modifying 1 element (False returned) - if (neg_count > 1): + if neg_count > 1: return False # val is updated for the next iteration val = elem - + # if the control reaches the end of the loop, True is returned return True + # DRIVER CODE print(check_1_modify_to_sorted([10, 5, 7])) print(check_1_modify_to_sorted([10, 5, 1])) -print(check_1_modify_to_sorted([1, 10, 5, 7])) \ No newline at end of file +print(check_1_modify_to_sorted([1, 10, 5, 7])) diff --git a/Solutions/80.py b/Solutions/80.py index 5aff30a..3556918 100644 --- a/Solutions/80.py +++ b/Solutions/80.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given the root of a binary tree, return a deepest node. @@ -11,7 +11,7 @@ / d Output = d -''' +""" # local import from DataStructures.Tree import Binary_Tree, Node @@ -19,40 +19,42 @@ # helper function to do the heavy lifting def deepest_node_helper(node): # the node is None, 0 and None is returned (base case of recursion) - if (not node): + if not node: return 0, None - + # if its a leaf node, 1 and the node is returned (base case of recursion) - if (not (node.left or node.right)): + if not (node.left or node.right): return 1, node - + # getting the left height and the deepest node of the left-subtree - if (node.left): + if node.left: left_height, left_node = deepest_node_helper(node.left) else: left_height, left_node = 0, None # getting the right height and the deepest node of the right-subtree - if (node.right): + if node.right: right_height, right_node = deepest_node_helper(node.right) else: right_height, right_node = 0, None - + # comparing the left and right heights and returning the deeper node and its height - if (left_height > right_height): - return left_height+1, left_node + if left_height > right_height: + return left_height + 1, left_node else: - return right_height+1, right_node + return right_height + 1, right_node + # FUNCTION TO PERFORM THE OPERATION def deepest_node(tree): _, node = deepest_node_helper(tree.root) return node.val + # DRIVER CODE -tree = Binary_Tree('a') -tree.root.left = Node('b') -tree.root.right = Node('c') -tree.root.left.left = Node('d') +tree = Binary_Tree("a") +tree.root.left = Node("b") +tree.root.right = Node("c") +tree.root.left.left = Node("d") -print(deepest_node(tree)) \ No newline at end of file +print(deepest_node(tree)) diff --git a/Solutions/81.py b/Solutions/81.py index 53e55b0..07f0a0c 100644 --- a/Solutions/81.py +++ b/Solutions/81.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a mapping of digits to letters (as in a phone number), and a digit string, return all possible letters the number could represent. @@ -8,16 +8,16 @@ Input = {'2': ['a', 'b', 'c'], '3': ['d', 'e', 'f']}, "23" Output = ['ad', 'ae', 'af', 'bd', 'be', 'bf', 'cd', 'ce', 'cf'] -''' +""" # FUNCTION TO PERFORM THE OPERATION def mapping(inp_map, string, res=[]): # returning the res array if the string is empty (base case for recursion) - if (not string): + if not string: return res - + # during the 1st call, adding the characters to the list - if (not res): + if not res: for elem in inp_map[string[0]]: res.append(elem) @@ -28,13 +28,14 @@ def mapping(inp_map, string, res=[]): # adding new character to each character present in res and adding the result to temp list for part in res: for elem in inp_map[string[0]]: - temp.append(part+elem) + temp.append(part + elem) # overwriting res res = temp - + # recursive call for the next charcter return mapping(inp_map, string[1:], res) + # DRIVER CODE -print(mapping({'2': ['a', 'b', 'c'], '3': ['d', 'e', 'f']}, "23", [])) -print(mapping({'2': ['a', 'b', 'c'], '3': ['d', 'e', 'f']}, "32", [])) \ No newline at end of file +print(mapping({"2": ["a", "b", "c"], "3": ["d", "e", "f"]}, "23", [])) +print(mapping({"2": ["a", "b", "c"], "3": ["d", "e", "f"]}, "32", [])) diff --git a/Solutions/82/82.py b/Solutions/82/82.py index d039e8c..edde59c 100644 --- a/Solutions/82/82.py +++ b/Solutions/82/82.py @@ -1,9 +1,9 @@ -''' +""" Problem: Using a read7() method that returns 7 characters from a file, implement readN(n) which reads n characters. For example, given a file with the content "Hello world", three read7() returns "Hello w", "orld" and then "". -''' +""" # global varibles # COUNT7 stores the number of characters read from the file (used in read7) COUNT7 = 0 @@ -16,16 +16,17 @@ def read7(): global COUNT7 # reading the next 7 characters - with open('data_82.txt', 'r') as f: + with open("data_82.txt", "r") as f: f.seek(COUNT7, 0) data = f.read(7) # incrementing COUNT7 by 7 COUNT7 += 7 - + # returning the data return data + # FUNCTION TO PERFORM THE OPERATION def readN(n): # declaring DATA as global variable @@ -33,7 +34,7 @@ def readN(n): # reading ceiling(n / 7) * 7 characters for _ in range(n // 7): - DATA += read7() + DATA += read7() DATA += read7() # storing the characters which are not needed and returning the characters asked for @@ -42,8 +43,9 @@ def readN(n): return temp + # DRIVER CODE print(readN(3)) print(readN(10)) print(readN(15)) -print(readN(25)) \ No newline at end of file +print(readN(25)) diff --git a/Solutions/83.py b/Solutions/83.py index 9866e39..4ba67ba 100644 --- a/Solutions/83.py +++ b/Solutions/83.py @@ -1,4 +1,4 @@ -''' +""" Problem: Invert a binary tree. @@ -17,7 +17,7 @@ c b \ / \ f e d -''' +""" # importing from the local datastructure module from DataStructures.Tree import Node, Binary_Tree @@ -28,20 +28,22 @@ def invert_helper(self): self.right, self.left = self.left, self.right # if the right child exists, the function is recursively called on it (to interchange its children too) - if (self.right != None): + if self.right != None: self.right.invert_helper() - + # if the left child exists, the function is recursively called on it (to interchange its children too) - if (self.left != None): + if self.left != None: self.left.invert_helper() + # FUNCTION TO PERFORM THE OPERATION def invert(self): self.root.invert_helper() + # adding the functions to the necessary class -setattr(Node, 'invert_helper', invert_helper) -setattr(Binary_Tree, 'invert', invert) +setattr(Node, "invert_helper", invert_helper) +setattr(Binary_Tree, "invert", invert) # DRIVER CODE tree = Binary_Tree("a") @@ -55,4 +57,4 @@ def invert(self): tree.invert() -print(tree) \ No newline at end of file +print(tree) diff --git a/Solutions/84.py b/Solutions/84.py index 25b35c6..85754da 100644 --- a/Solutions/84.py +++ b/Solutions/84.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a matrix of 1s and 0s, return the number of "islands" in the matrix. @@ -13,7 +13,7 @@ 1 1 0 0 1 1 1 0 0 1 Output = 4 (this matrix has 4 islands) -''' +""" # helper function to return the valid neighbours of a point def get_neighbours(pos, grid_shape): @@ -25,24 +25,25 @@ def get_neighbours(pos, grid_shape): # getting all positions surrounding the point (invalid ones included too) pos_list = [ - (i-1, j-1), - (i-1, j), - (i-1, j+1), - (i, j-1), - (i, j+1), - (i+1, j-1), - (i+1, j), - (i+1, j+1) + (i - 1, j - 1), + (i - 1, j), + (i - 1, j + 1), + (i, j - 1), + (i, j + 1), + (i + 1, j - 1), + (i + 1, j), + (i + 1, j + 1), ] # adding the valid positions to the res list for pos_test in pos_list: y_test, x_test = pos_test - if ((x_test >= 0 and x_test < m) and (y_test >= 0 and y_test < n)): + if (x_test >= 0 and x_test < m) and (y_test >= 0 and y_test < n): res.append(pos_test) - + return res + # helper function to remove the island def remove_island(mat, pos): # using bfs to remove the islands @@ -55,10 +56,11 @@ def remove_island(mat, pos): i, j = curr # if the position contains a 1, its replaced with 0 and the neighbours added to the queue - if (mat[i][j] == 1): + if mat[i][j] == 1: mat[i][j] = 0 queue.extend(get_neighbours((i, j), (len(mat), len(mat[0])))) + # FUNCTION TO PERFORM THE OPERATION def island_count(mat): # initializing the island count to 0 @@ -68,17 +70,20 @@ def island_count(mat): for i in range(len(mat)): for j in range(len(mat[0])): # if an island is encountered, remove_island function is called and the island count incremented - if (mat[i][j] == 1): + if mat[i][j] == 1: remove_island(mat, (i, j)) count += 1 - + return count + # DRIVER CODE -mat = [[1, 0, 0, 0, 0], - [0, 0, 1, 1, 0], - [0, 1, 1, 0, 0], - [0, 0, 0, 0, 0], - [1, 1, 0, 0, 1], - [1, 1, 0, 0, 1]] -print(island_count(mat)) \ No newline at end of file +mat = [ + [1, 0, 0, 0, 0], + [0, 0, 1, 1, 0], + [0, 1, 1, 0, 0], + [0, 0, 0, 0, 0], + [1, 1, 0, 0, 1], + [1, 1, 0, 0, 1], +] +print(island_count(mat)) diff --git a/Solutions/85.py b/Solutions/85.py index c27c1d1..12482be 100644 --- a/Solutions/85.py +++ b/Solutions/85.py @@ -1,15 +1,16 @@ -''' +""" Problem: Given three 32-bit integers x, y, and b, return x if b is 1 and y if b is 0, using only mathematical or bit operations. You can assume b can only be 1 or 0. -''' +""" # FUNCTION TO PERFORM THE OPERATION def switch_on_int(x, y, b): # returning the necessary number based on the value of b, abs(-1)=1, so if b=0, y is returned, else x is returned - return (x * b) + (y * abs(b-1)) + return (x * b) + (y * abs(b - 1)) + # DRIVER CODE print(switch_on_int(6, 8, 1)) -print(switch_on_int(6, 8, 0)) \ No newline at end of file +print(switch_on_int(6, 8, 0)) diff --git a/Solutions/86.py b/Solutions/86.py index 879b720..79e3dae 100644 --- a/Solutions/86.py +++ b/Solutions/86.py @@ -1,4 +1,4 @@ -''' +""" Problem: You are given a string of parentheses. @@ -12,30 +12,33 @@ Input = ")(" Output = 2 -''' +""" # FUNCTION TO PERFORM THE OPERATION def num_parentheses_remove(expression, stack=[], num_removed=0): # returning num_removed if the expression and stack is empty - if (not expression and not stack): + if not expression and not stack: return num_removed # returning num_removed+stack size if the expression and stack isn't empty - elif (not expression): - return (len(stack) + num_removed) - + elif not expression: + return len(stack) + num_removed + # if the last paranthesis can be balanced, its opening part is removed from the stack - if ((expression[0] == ')') and (stack and stack[-1] == '(')): + if (expression[0] == ")") and (stack and stack[-1] == "("): stack.pop() return num_parentheses_remove(expression[1:], stack, num_removed) - + # getting the number of changes if the current paranthesis is added to stack - num_added_to_stack = num_parentheses_remove(expression[1:], stack+[expression[0]], num_removed) + num_added_to_stack = num_parentheses_remove( + expression[1:], stack + [expression[0]], num_removed + ) # getting the number of changes if the current paranthesis is ignored (removed) - num_ignored = num_parentheses_remove(expression[1:], stack, num_removed+1) + num_ignored = num_parentheses_remove(expression[1:], stack, num_removed + 1) # returning the minimum of the 2 (num_added_to_stack, num_ignored) return min(num_added_to_stack, num_ignored) + # DIVER CODE print(num_parentheses_remove("()())()")) -print(num_parentheses_remove(")(")) \ No newline at end of file +print(num_parentheses_remove(")(")) diff --git a/Solutions/87.py b/Solutions/87.py index fa8d013..daf1bb8 100644 --- a/Solutions/87.py +++ b/Solutions/87.py @@ -1,4 +1,4 @@ -''' +""" Problem: A rule looks like this: @@ -20,41 +20,42 @@ A NW B A N B is considered valid. -''' +""" # global vaiable to store the opposites -OPPOSITES = {'N': 'S', 'S': 'N', 'E': 'W', 'W': 'E'} +OPPOSITES = {"N": "S", "S": "N", "E": "W", "W": "E"} # node class (stores the neighbours) -class Node(): +class Node: # initialization def __init__(self, val): self.val = val - self.neighbours = {'N': set(), 'E': set(), 'S': set(), 'W': set()} - + self.neighbours = {"N": set(), "E": set(), "S": set(), "W": set()} + # representation function def __repr__(self): - return f'{self.val}' - + return f"{self.val}" + # equality condition (operation overloading) def __eq__(self, other): - if (type(other) == Node): - return (self.val == other.val) - elif (type(other) == str): - return (self.val == other) + if type(other) == Node: + return self.val == other.val + elif type(other) == str: + return self.val == other else: return False - + # defining the hash function as its needed in Map class def __hash__(self): return hash(self.val) + # map class -class Map(): +class Map: # initialization def __init__(self): self.nodes = {} - + # FUNCTION TO PERFORM THE OPERATION def add_rule(self, rule): # breaking the rule into its components @@ -65,41 +66,44 @@ def add_rule(self, rule): node2 = Node(node2) # cheking for the existance of node1 - if (node1 not in self.nodes): + if node1 not in self.nodes: self.nodes[node1.val] = node1 else: node1 = self.nodes[node1.val] - + # cheking for the existance of node2 - if (node2 not in self.nodes): + if node2 not in self.nodes: self.nodes[node2.val] = node2 else: node2 = self.nodes[node2.val] - + # for each character in direction, the neighbours are updated recursively for char in direction: # if the node is not valid, RuntimeError is raised - if ((node1 in node2.neighbours[char]) or (node2 in node1.neighbours[OPPOSITES[char]])): + if (node1 in node2.neighbours[char]) or ( + node2 in node1.neighbours[OPPOSITES[char]] + ): raise RuntimeError # recursive calling for all neighbours for node in node1.neighbours[char]: - self.add_rule(f'{node} {char} {node2}') - + self.add_rule(f"{node} {char} {node2}") + # adding the rule to the calling node for char in direction: node2.neighbours[char].add(node1) node1.neighbours[OPPOSITES[char]].add(node2) + # DRIVER CODE m = Map() -m.add_rule('A N B') -print('Rule Applied!') -m.add_rule('B NE C') -print('Rule Applied!') +m.add_rule("A N B") +print("Rule Applied!") +m.add_rule("B NE C") +print("Rule Applied!") try: - m.add_rule('C N A') + m.add_rule("C N A") except RuntimeError: - print("Invalid Rule!") \ No newline at end of file + print("Invalid Rule!") diff --git a/Solutions/88.py b/Solutions/88.py index e515e30..8aa2ea0 100644 --- a/Solutions/88.py +++ b/Solutions/88.py @@ -1,31 +1,32 @@ -''' +""" Problem: Implement division of two positive integers without using the division, multiplication, or modulus operators. Return the quotient as an integer, ignoring the remainder. -''' +""" # FUNCTION TO PERFORM THE OPERATION def div(dividend, divisor): # if the divisor is 0, division is not possible - if (divisor == 0): + if divisor == 0: return None - + # quotient stores the result of the division quotient = 0 # while the dividend is larger than 0, it might be divided my the divisor - while (dividend > 0): + while dividend > 0: # divisor is subtracted from the dividend dividend -= divisor # if the dividend is still larger than 0, the quotient is incremented - if (dividend >= 0): + if dividend >= 0: quotient += 1 - + # the quotient is returned return quotient + # DRIVER CODE print(div(1, 0)) print(div(1, 1)) @@ -33,4 +34,4 @@ def div(dividend, divisor): print(div(12, 3)) print(div(13, 3)) print(div(25, 5)) -print(div(25, 7)) \ No newline at end of file +print(div(25, 7)) diff --git a/Solutions/89.py b/Solutions/89.py index 2654bed..8a30aa9 100644 --- a/Solutions/89.py +++ b/Solutions/89.py @@ -1,33 +1,37 @@ -''' +""" Problem: Determine whether a tree is a valid binary search tree. A binary search tree is a tree with two children, left and right, and satisfies the BST constraint. BST constraint: the key in the left child must be less than or equal to the root and the key in the right child must be greater than or equal to the root. -''' +""" # importing tree from datastructure from DataStructures.Tree import Binary_Tree, Binary_Search_Tree, Node # helper function for the main operation def bst_check_helper(node): - # if the passed node (only applicable for the root) is empty, True is returned [recursion base case] - if (node == None): - return True - - # if its a leaf node, True is returned [recursion base case] - if (node.left == None and node.right == None): - return True - # if the children nodes exist but doesn't follow the BST constraint, False is returned - elif ((node.left and node.left.val > node.val) or (node.right and node.right.val < node.val)): - return False - # returning the value for the bst check on both left and right children - return (bst_check_helper(node.left) and bst_check_helper(node.right)) + # if the passed node (only applicable for the root) is empty, True is returned [recursion base case] + if node == None: + return True + + # if its a leaf node, True is returned [recursion base case] + if node.left == None and node.right == None: + return True + # if the children nodes exist but doesn't follow the BST constraint, False is returned + elif (node.left and node.left.val > node.val) or ( + node.right and node.right.val < node.val + ): + return False + # returning the value for the bst check on both left and right children + return bst_check_helper(node.left) and bst_check_helper(node.right) + # FUNCTION TO PERFORM THE OPERATION def bst_check(tree): - return bst_check_helper(tree.root) + return bst_check_helper(tree.root) + # DRIVER CODE tree = Binary_Search_Tree() @@ -53,4 +57,4 @@ def bst_check(tree): tree = Binary_Tree(5) tree.root.left = Node(6) tree.root.right = Node(5) -print(f"BST Check Status: {bst_check(tree)}") \ No newline at end of file +print(f"BST Check Status: {bst_check(tree)}") diff --git a/Solutions/90.py b/Solutions/90.py index 4ab9794..4d1cb31 100644 --- a/Solutions/90.py +++ b/Solutions/90.py @@ -1,8 +1,8 @@ -''' +""" Problem: Given an integer n and a list of integers l, write a function that randomly generates a number from 0 to n-1 that isn't in l (uniform). -''' +""" # matplotlib is used to plt the distribution (not mandatory) # randint is used to generate the random number @@ -12,14 +12,15 @@ # FUNCTION TO PERFORM THE OPERATION def generate_num_not_in_data(n, data): # a random number is generated in the range [0, n-1] - num = randint(0, n-1) + num = randint(0, n - 1) # if the number is not present in the supplied list, its returned; else the function is called recursively - if (num in data): + if num in data: return generate_num_not_in_data(n, data) - + return num + # DRIVER CODE data = set([1, 3, 5]) results = {} @@ -27,7 +28,7 @@ def generate_num_not_in_data(n, data): for i in range(100000): val = generate_num_not_in_data(7, data) - if (val in results): + if val in results: results[val] += 1 else: results[val] = 1 @@ -39,5 +40,5 @@ def generate_num_not_in_data(n, data): x.append(i) y.append(results[i]) -plt.bar(x=x, height=y, edgecolor='black') -plt.show() \ No newline at end of file +plt.bar(x=x, height=y, edgecolor="black") +plt.show() diff --git a/Solutions/91.py b/Solutions/91.py index ceb7ee9..b3289db 100644 --- a/Solutions/91.py +++ b/Solutions/91.py @@ -1,4 +1,4 @@ -''' +""" Problem: What does the below code snippet print out? How can we fix the anonymous functions to behave as we'd expect? @@ -9,7 +9,7 @@ for f in functions: print(f()) -''' +""" # The code is expected to print 9, 9, ..., 9 (10 times) # This is beacuse the value of i is set to 9 and is not changed during iteration @@ -17,9 +17,9 @@ functions = [] for i in range(10): - functions.append(lambda : i) + functions.append(lambda: i) -i = 0 # MODIFICATION +i = 0 # MODIFICATION for f in functions: print(f()) - i += 1 # MODIFICATION \ No newline at end of file + i += 1 # MODIFICATION diff --git a/Solutions/92.py b/Solutions/92.py index 04413ca..ffacf78 100644 --- a/Solutions/92.py +++ b/Solutions/92.py @@ -1,4 +1,4 @@ -''' +""" Problem: We're given a hashmap with a key courseId and value a list of courseIds, which represents that the prerequsite of courseId is courseIds. @@ -9,41 +9,44 @@ Input = {'CSC300': ['CSC100', 'CSC200'], 'CSC200': ['CSC100'], 'CSC100': []} Output = ['CSC100', 'CSC200', 'CSCS300'] -''' +""" # helper function to get the order for the pre-requisites for a course def get_order_helper(hash_map, course, order, processed, break_limit=None, curr=0): # getting the break limit (function calls implying its not possible to order the course) - if (not break_limit): + if not break_limit: break_limit = len(hash_map) - + # if the current function calls exceed the break limit None is returned for order & processed - if (break_limit < curr): + if break_limit < curr: return None, None - + # if the course doesn't have any pre-req - if (hash_map[course] == []): + if hash_map[course] == []: # if the course has not been processed, its added to order + processed - if (course not in processed): + if course not in processed: order.append(course) processed.add(course) # returning order + processed return order, processed - + else: # for each pre-req, we update the order and processed for pre_req in hash_map[course]: - order, processed = get_order_helper(hash_map, pre_req, order, processed, break_limit, curr+1) + order, processed = get_order_helper( + hash_map, pre_req, order, processed, break_limit, curr + 1 + ) # if the ordering is not possible None is returned for order & processed - if (order == None): + if order == None: return None, None - + # adding the course to order + processed order.append(course) processed.add(course) # returning order + processed return order, processed + # FUNCTION TO PERFORM THE OPERATION def get_order(hash_map): # order stores the resultant order @@ -54,42 +57,41 @@ def get_order(hash_map): # iterating over the hash_map for course_parent in hash_map: # if the node (course) hasn't been processed, we process it - if (course_parent not in processed): + if course_parent not in processed: # checking all the pre-requisite for the current course for course in hash_map[course_parent]: # if the node (course pre-requisite) hasn't been processed, we process it - if (course not in processed): + if course not in processed: # getting the order and processed nodes - order, processed = get_order_helper(hash_map, course, order, processed) + order, processed = get_order_helper( + hash_map, course, order, processed + ) # if order == None ordering of the given courses is not possible - if (order == None): + if order == None: return None # adding the course to order and processed order.append(course_parent) processed.add(course_parent) - + return order + # DRIVER CODE -prereqs = { - 'CSC300': ['CSC100', 'CSC200'], - 'CSC200': ['CSC100'], - 'CSC100': [] -} +prereqs = {"CSC300": ["CSC100", "CSC200"], "CSC200": ["CSC100"], "CSC100": []} print(get_order(prereqs)) prereqs = { - 'CSC400': ['CSC300'], - 'CSC300': ['CSC100', 'CSC200'], - 'CSC200': ['CSC100'], - 'CSC100': [] + "CSC400": ["CSC300"], + "CSC300": ["CSC100", "CSC200"], + "CSC200": ["CSC100"], + "CSC100": [], } print(get_order(prereqs)) prereqs = { - 'CSC400': ['CSC300'], - 'CSC300': ['CSC100', 'CSC200'], - 'CSC200': ['CSC100'], - 'CSC100': ['CSC400'] + "CSC400": ["CSC300"], + "CSC300": ["CSC100", "CSC200"], + "CSC200": ["CSC100"], + "CSC100": ["CSC400"], } -print(get_order(prereqs)) \ No newline at end of file +print(get_order(prereqs)) diff --git a/Solutions/93.py b/Solutions/93.py index 80244b7..c4d95dc 100644 --- a/Solutions/93.py +++ b/Solutions/93.py @@ -1,9 +1,9 @@ -''' +""" Problem: Given a tree, find the largest tree/subtree that is a BST. Given a tree, return the size of the largest tree/subtree that is a BST. -''' +""" # local import from the DataStructres class from DataStructures.Tree import Binary_Tree, Node @@ -11,45 +11,51 @@ # function do perform the main heavylifting def get_largest_bst_size_helper(node): # base case 1 of recursion (node is None) - if (not node): + if not node: return 0, node, True, 999999, -999999 # base case 1 of recursion (leaf node) - if (not node.left and not node.right): + if not node.left and not node.right: return 1, node, True, node.val, node.val # getting the left and right results (height of largest bst, root of largest bst, if the entire sub-tree (left/right) is a bst, max value in the largest bst, min value in the largest bst) - l_height, l_root, l_is_bst, l_max_val, l_min_val = get_largest_bst_size_helper(node.left) - r_height, r_root, r_is_bst, r_max_val, r_min_val = get_largest_bst_size_helper(node.right) + l_height, l_root, l_is_bst, l_max_val, l_min_val = get_largest_bst_size_helper( + node.left + ) + r_height, r_root, r_is_bst, r_max_val, r_min_val = get_largest_bst_size_helper( + node.right + ) # if both the left & right sub-trees are bst - if (l_is_bst and r_is_bst): + if l_is_bst and r_is_bst: # if both the left and right nodes exist - if (node.left and node.right): + if node.left and node.right: # checking for bst condition - if (node.val > l_max_val and node.val < r_min_val): - return (l_height+r_height+1), node, True, r_max_val, l_min_val + if node.val > l_max_val and node.val < r_min_val: + return (l_height + r_height + 1), node, True, r_max_val, l_min_val else: # if the left node exists, if the bst condition is met, the values are returned - if (node.left and node.val > l_max_val): - return l_height+1, node, True, node.val, l_min_val + if node.left and node.val > l_max_val: + return l_height + 1, node, True, node.val, l_min_val # if the right node exist, if the bst condition is met, the values are returned - elif (node.right and node.val < r_min_val): - return r_height+1, node, True, r_max_val, node.val - + elif node.right and node.val < r_min_val: + return r_height + 1, node, True, r_max_val, node.val + # if either of the left or right sub-trees is not a bst, the larger one is returned - if (l_height > r_height): + if l_height > r_height: return l_height, l_root, False, l_max_val, l_min_val else: return r_height, r_root, False, r_max_val, r_min_val + # FUNCTION TO PERFORM THE OPERATION def get_largest_bst_size(self): size, node, _, _, _ = get_largest_bst_size_helper(self.root) return size, node.val + # adding the fucntion to the Binary_Tree class -setattr(Binary_Tree, 'get_largest_bst_size', get_largest_bst_size) +setattr(Binary_Tree, "get_largest_bst_size", get_largest_bst_size) # DRIVER CODE a = Node(3) @@ -135,4 +141,4 @@ def get_largest_bst_size(self): tree.root = a print(tree) -print("Size: {}\tNode Val: {}".format(*tree.get_largest_bst_size())) \ No newline at end of file +print("Size: {}\tNode Val: {}".format(*tree.get_largest_bst_size())) diff --git a/Solutions/94.py b/Solutions/94.py index d7d56ec..6a344f8 100644 --- a/Solutions/94.py +++ b/Solutions/94.py @@ -1,19 +1,19 @@ -''' +""" Problem: Given a binary tree of integers, find the maximum path sum between two nodes. The path must go through at least one node, and does not need to go through the root. -''' +""" -#local imports from DataStructure +# local imports from DataStructure from DataStructures.Tree import Node, Binary_Tree # helper function to do the heavy-lifting def get_max_path_sum_helper(node, current_max_sum, overall_max_sum): # if the node is None (empty tree/ leaf's children), the path sum is 0 - if (not node): + if not node: return 0 - + # getting the left and right max path sum l_max_sum = get_max_path_sum_helper(node.left, current_max_sum, overall_max_sum) r_max_sum = get_max_path_sum_helper(node.right, current_max_sum, overall_max_sum) @@ -26,18 +26,27 @@ def get_max_path_sum_helper(node, current_max_sum, overall_max_sum): # right max sum + node's val [the left subtree is not selected] # left max sum + node's val + right max sum [the entire subtree is selected] # ) - current_max_sum = max(current_max_sum+node.val, current_max_sum, node.val, l_max_sum+node.val, r_max_sum+node.val, l_max_sum+node.val+r_max_sum) + current_max_sum = max( + current_max_sum + node.val, + current_max_sum, + node.val, + l_max_sum + node.val, + r_max_sum + node.val, + l_max_sum + node.val + r_max_sum, + ) # overall max sum is updated as per requirement overall_max_sum = max(current_max_sum, overall_max_sum) return overall_max_sum + # FUNCTION TO PERFORM THE OPERATION def get_max_path_sum(self): return get_max_path_sum_helper(self.root, 0, 0) + # attaching the function to the Binary_Tree class -setattr(Binary_Tree, 'get_max_path_sum', get_max_path_sum) +setattr(Binary_Tree, "get_max_path_sum", get_max_path_sum) # DRIVER CODE tree = Binary_Tree() @@ -60,4 +69,4 @@ def get_max_path_sum(self): tree.root.left.left = Node(4) print(tree) -print(tree.get_max_path_sum()) \ No newline at end of file +print(tree.get_max_path_sum()) diff --git a/Solutions/95.py b/Solutions/95.py index 91a9421..b75abbe 100644 --- a/Solutions/95.py +++ b/Solutions/95.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a number represented by a list of digits, find the next greater permutation of a number, in terms of lexicographic ordering. @@ -14,7 +14,7 @@ Input = [3,2,1] Output = [1,2,3] -''' +""" # FUNCTION TO PERFORM THE OPERATION def get_next(arr): @@ -22,17 +22,17 @@ def get_next(arr): length = len(arr) # if arr has 0 or 1 elements, its returned - if (length < 2): + if length < 2: return arr # looping arr from the end to the beginning for index in range(length - 1, -1, -1): # finding the last element arranged in ascending order - if (index > 0 and arr[index - 1] < arr[index]): + if index > 0 and arr[index - 1] < arr[index]: break # if index is 0 (arr is sorted in descending order), arr is reversed - if (index == 0): + if index == 0: arr.reverse() else: @@ -40,8 +40,8 @@ def get_next(arr): # looping over arr from the end to the index for k in range(length - 1, index - 1, -1): # getting the element to swap - if (arr[k] > arr[index - 1]): - arr[k], arr[index - 1] = arr[index - 1], arr[k] + if arr[k] > arr[index - 1]: + arr[k], arr[index - 1] = arr[index - 1], arr[k] break # arranging the other elements in proper order @@ -51,10 +51,11 @@ def get_next(arr): return arr + # DRIVER CODE -print(get_next([1,2,3])) -print(get_next([1,3,2])) -print(get_next([2,1,3])) -print(get_next([2,3,1])) -print(get_next([3,1,2])) -print(get_next([3,2,1])) \ No newline at end of file +print(get_next([1, 2, 3])) +print(get_next([1, 3, 2])) +print(get_next([2, 1, 3])) +print(get_next([2, 3, 1])) +print(get_next([3, 1, 2])) +print(get_next([3, 2, 1])) diff --git a/Solutions/96.py b/Solutions/96.py index 09f3b03..f07d5a6 100644 --- a/Solutions/96.py +++ b/Solutions/96.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a number in the form of a list of digits, return all possible permutations. @@ -7,31 +7,32 @@ Input = [1,2,3] Output = [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] -''' +""" # FUNCTION TO PERFORM THE OPERATION def permute(arr, l=0, r=None, res=[]): # getting the end position (in case it is not passed) - if (r == None): - r = len(arr)-1 + if r == None: + r = len(arr) - 1 # adding the current permutaion in case the end has been reached - if (l == r): + if l == r: res.append(list(arr)) - else: - for i in range(l, r+1): + else: + for i in range(l, r + 1): # generating all permutation by changing i'th element with all other elements arr[l], arr[i] = arr[i], arr[l] # recursive calling - permute(arr, l+1, r, res) + permute(arr, l + 1, r, res) # backtracking arr[l], arr[i] = arr[i], arr[l] - + return res + # DRIVER CODE -print(permute([1,2,3], res=[])) -print(permute([1,2], res=[])) +print(permute([1, 2, 3], res=[])) +print(permute([1, 2], res=[])) print(permute([1], res=[])) -print(permute([], res=[])) \ No newline at end of file +print(permute([], res=[])) diff --git a/Solutions/97.py b/Solutions/97.py index 7a11ec8..a5ea27c 100644 --- a/Solutions/97.py +++ b/Solutions/97.py @@ -1,4 +1,4 @@ -''' +""" Problem: Write a map implementation with a get function that lets you retrieve the value of a key at a particular time. @@ -24,82 +24,84 @@ d.set(1, 1, 0) # set key 1 to value 1 at time 0 d.set(1, 2, 0) # set key 1 to value 2 at time 0 d.get(1, 0) # get key 1 at time 0 should be 2 -''' +""" # Node class for storing the data (for Double Linked List) -class Node(): +class Node: # initialization def __init__(self, val_list, time): self.val_list = val_list self.time = time self.next = None self.prev = None - + # string function def __str__(self): - if (self.next): - return (f"{self.val_list} ({self.time}) <=> {str(self.next)}") + if self.next: + return f"{self.val_list} ({self.time}) <=> {str(self.next)}" else: return f"{self.val_list} ({self.time})" - + # equality function def __eq__(self, other): - if (type(other) != Node): + if type(other) != Node: return False - - return (self.time == other.time) + + return self.time == other.time + # Double Linked List to maintain the nodes -class Double_Linked_List(): +class Double_Linked_List: # initialization def __init__(self): self.head = None self.rear = None self.length = 0 - + # string function def __str__(self): return str(self.head) - + # boolean function def __bool__(self): return bool(self.head) - + # function to add the value at the end of the linked list def add(self, val_list, time): self.length += 1 - if (self.head == None): + if self.head == None: self.head = Node(val_list, time) self.rear = self.head - + else: self.rear.next = Node(val_list, time) self.rear.next.prev = self.rear self.rear = self.rear.next + # Map class to perform the necessary operations -class Map(): +class Map: # initialization def __init__(self): self.linked_list = Double_Linked_List() - + # FUNCTION TO PERFORM THE OPERATION (set) def set(self, key, value, time): # if the linked list is empty, the value is added - if (not self.linked_list): + if not self.linked_list: self.linked_list.add({key: value}, time) - + else: # getting the head of the linked list pos = self.linked_list.head # iterating till a node containing larger time is found - while (pos and pos.time < time): + while pos and pos.time < time: pos = pos.next - + # if the node has to inserted at the begining - if (pos == self.linked_list.head): + if pos == self.linked_list.head: # creating a new node to hold the values at the new time temp_val_list = {key: value} new_node = Node(temp_val_list, time) @@ -108,11 +110,11 @@ def set(self, key, value, time): self.linked_list.head.prev = new_node new_node.next = self.linked_list.head self.head = new_node - + # if we haven't reached the end of the linked list - if (pos): + if pos: # if the time is equal to the given time, the value is updated - if (time == pos.time): + if time == pos.time: pos.val_list[key] = value else: # creating a new node to hold the values at the new time @@ -130,29 +132,29 @@ def set(self, key, value, time): temp_val_list = dict(self.linked_list.rear.val_list) temp_val_list[key] = value self.linked_list.add(temp_val_list, time) - + # FUNCTION TO PERFORM THE OPERATION (get) def get(self, key, time): # checking if the linked list has any value - if (not self.linked_list): + if not self.linked_list: return None - + # getting the head of the linked list pos = self.linked_list.head # iterating till a node containing larger time is found - while (pos and pos.time < time): + while pos and pos.time < time: pos = pos.next # if we have reached the end of the linked list - if (not pos): + if not pos: try: temp = self.linked_list.rear.val_list[key] return temp except: return None # if we have found the time - elif (pos and pos.time == time): + elif pos and pos.time == time: try: temp = pos.val_list[key] return temp @@ -166,24 +168,25 @@ def get(self, key, time): except: return None - # DRIVER CODE + +# DRIVER CODE d = Map() -d.set(1, 1, 0) # set key 1 to value 1 at time 0 -d.set(1, 2, 2) # set key 1 to value 2 at time 2 +d.set(1, 1, 0) # set key 1 to value 1 at time 0 +d.set(1, 2, 2) # set key 1 to value 2 at time 2 # print(d.linked_list) -print(d.get(1, 1)) # get key 1 at time 1 should be 1 -print(d.get(1, 3)) # get key 1 at time 3 should be 2 +print(d.get(1, 1)) # get key 1 at time 1 should be 1 +print(d.get(1, 3)) # get key 1 at time 3 should be 2 print() d = Map() -d.set(1, 1, 5) # set key 1 to value 1 at time 5 +d.set(1, 1, 5) # set key 1 to value 1 at time 5 # print(d.linked_list) -print(d.get(1, 0)) # get key 1 at time 0 should be null -print(d.get(1, 10)) # get key 1 at time 10 should be 1 +print(d.get(1, 0)) # get key 1 at time 0 should be null +print(d.get(1, 10)) # get key 1 at time 10 should be 1 print() d = Map() -d.set(1, 1, 0) # set key 1 to value 1 at time 0 -d.set(1, 2, 0) # set key 1 to value 2 at time 0 +d.set(1, 1, 0) # set key 1 to value 1 at time 0 +d.set(1, 2, 0) # set key 1 to value 2 at time 0 # print(d.linked_list) -print(d.get(1, 0)) # get key 1 at time 0 should be 2 \ No newline at end of file +print(d.get(1, 0)) # get key 1 at time 0 should be 2 diff --git a/Solutions/98.py b/Solutions/98.py index 317a264..e2ad84e 100644 --- a/Solutions/98.py +++ b/Solutions/98.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given a 2D board of characters and a word, find if the word exists in the grid. @@ -21,19 +21,14 @@ Input = board, "ABCB" Output = false -''' +""" # helper function for getting all the vaild neighbours def get_neighbors(pos, n, m): i, j = pos # getting all neighbours - neighbors = [ - (i+1, j), - (i-1, j), - (i, j-1), - (i, j+1) - ] + neighbors = [(i + 1, j), (i - 1, j), (i, j - 1), (i, j + 1)] result = [] @@ -41,64 +36,63 @@ def get_neighbors(pos, n, m): for pos in neighbors: i, j = pos - if (i >= 0 and i < n): - if (j >= 0 and j < m): + if i >= 0 and i < n: + if j >= 0 and j < m: result.append(pos) - + return result + # helper function to perform the heavy lifting def exists_helper(board, pos, string, visited=set()): # if the string has been exhausted True is returned [BASE CASE FOR RECURSION] - if (not string): + if not string: return True - + # getting the neighbours of the current position neighbors = get_neighbors(pos, len(board), len(board[0])) - + # checking all neighbours for pos_neighbor in neighbors: i, j = pos_neighbor - + # if the next character of the string is found, we visit it and check if the rest of the string can be found - if ((board[i][j] == string[0]) and (pos_neighbor not in visited)): + if (board[i][j] == string[0]) and (pos_neighbor not in visited): # adding the current position to visited set visited.add((i, j)) # checking if the rest of the string exists - if (exists_helper(board, (i, j), string[1:], visited)): + if exists_helper(board, (i, j), string[1:], visited): return True - + # removing the current position from visited set [BACKTRACKING] visited.remove((i, j)) - + return False + # FUNCTION TO PERFORM THE OPERATION def exists(board, string): # returning True if an empty string is passed - if (not string): + if not string: return True # looping over the matrix for index_r, row in enumerate(board): for index, elem in enumerate(row): # if the 1st character match is found we execute the helper function - if (string[0] == elem): + if string[0] == elem: # if the helper function returns True, the string has been found (True is returned) - if (exists_helper(board, (index_r, index), string[1:], set())): + if exists_helper(board, (index_r, index), string[1:], set()): return True - + # False is returned is after traversing the entire board, the string is not found return False + # DRIVER CODE -board = [ - ['A','B','C','E'], - ['S','F','C','S'], - ['A','D','E','E'] -] +board = [["A", "B", "C", "E"], ["S", "F", "C", "S"], ["A", "D", "E", "E"]] print(exists(board, "ABCCED")) print(exists(board, "SEE")) -print(exists(board, "ABCB")) \ No newline at end of file +print(exists(board, "ABCB")) diff --git a/Solutions/99.py b/Solutions/99.py index f7eeb90..8c8c7fc 100644 --- a/Solutions/99.py +++ b/Solutions/99.py @@ -1,4 +1,4 @@ -''' +""" Problem: Given an unsorted array of integers, find the length of the longest consecutive elements sequence. @@ -8,7 +8,7 @@ Input = [100, 4, 200, 1, 3, 2] Output = 4 ([1, 2, 3, 4]) -''' +""" # FUNCTION TO PERFORM THE OPERATION def longest_consecutive_elements_sequence(arr): @@ -18,12 +18,12 @@ def longest_consecutive_elements_sequence(arr): longest = 0 # looping till val_set has some value - while (val_set): + while val_set: # getting a random element from val_set for i in val_set: elem = i break - + # removing the element from the set # creating length temp for checking the lenth of the sequence the element is a part of # creating the max and min limit of the sequence @@ -33,29 +33,30 @@ def longest_consecutive_elements_sequence(arr): min_lim = elem - 1 # iterating till the max or min limit value is in the set - while ((max_lim in val_set) or (min_lim in val_set)): + while (max_lim in val_set) or (min_lim in val_set): # if the max limit is in the set, its removed and max limit and the length of the sequence updated - if (max_lim in val_set): + if max_lim in val_set: length_temp += 1 val_set.remove(max_lim) max_lim += 1 - + # if the min limit is in the set, its removed and min limit and the length of the sequence updated - if (min_lim in val_set): + if min_lim in val_set: length_temp += 1 val_set.remove(min_lim) min_lim -= 1 - + # if the length of the sequence exceeds the longest length, longest is updated - if (longest < length_temp): + if longest < length_temp: longest = length_temp - + # NOTE: This function runs in O(n) even though it has 3 loops (2 nested) return longest + # DRIVER CODE print(longest_consecutive_elements_sequence([100, 4, 200, 1])) print(longest_consecutive_elements_sequence([100, 4, 200, 1, 3])) print(longest_consecutive_elements_sequence([100, 4, 200, 2, 3])) print(longest_consecutive_elements_sequence([100, 4, 200, 1, 3, 2])) -print(longest_consecutive_elements_sequence([100, 4, 200, 1, 3, 2, 5])) \ No newline at end of file +print(longest_consecutive_elements_sequence([100, 4, 200, 1, 3, 2, 5])) diff --git a/Solutions/DataStructures/Graph.py b/Solutions/DataStructures/Graph.py index 976b3ee..b944f91 100644 --- a/Solutions/DataStructures/Graph.py +++ b/Solutions/DataStructures/Graph.py @@ -1,11 +1,11 @@ class GraphUndirectedUnweighted: - ''' + """ Graph Undirected Unweighted Class Functions: add_node: function to add a node in the graph add_edge: function to add an edge between 2 nodes in the graph - ''' + """ def __init__(self) -> None: self.connections = {} @@ -32,13 +32,13 @@ def add_edge(self, node1: int, node2: int) -> None: class GraphDirectedUnweighted: - ''' + """ Graph Directed Unweighted Class Functions: add_node: function to add a node in the graph add_edge: function to add an edge between 2 nodes in the graph - ''' + """ def __init__(self) -> None: self.connections = {} @@ -64,13 +64,13 @@ def add_edge(self, node1: int, node2: int) -> None: class GraphUndirectedWeighted: - ''' + """ Graph Undirected Weighted Class Functions: add_node: function to add a node in the graph add_edge: function to add an edge between 2 nodes in the graph - ''' + """ def __init__(self) -> None: self.connections = {} diff --git a/Solutions/DataStructures/LinkedList.py b/Solutions/DataStructures/LinkedList.py index 9f0b68c..21a9fca 100644 --- a/Solutions/DataStructures/LinkedList.py +++ b/Solutions/DataStructures/LinkedList.py @@ -2,9 +2,9 @@ class Node: - ''' + """ Node Class for the nodes of a Linked List - ''' + """ def __init__(self, val: int = None) -> None: self.val = val @@ -12,17 +12,17 @@ def __init__(self, val: int = None) -> None: def __repr__(self) -> str: if self.next: - return (f"{str(self.val)} => {str(self.next)}") + return f"{str(self.val)} => {str(self.next)}" return str(self.val) class LinkedList: - ''' + """ Linked List Class Functions: add: function to add a node at the end of the linked list - ''' + """ def __init__(self) -> None: self.head = None diff --git a/Solutions/DataStructures/Queue.py b/Solutions/DataStructures/Queue.py index def8bf1..de53d67 100644 --- a/Solutions/DataStructures/Queue.py +++ b/Solutions/DataStructures/Queue.py @@ -1,5 +1,5 @@ class Queue: - ''' + """ Queue Class for FIFO Structure Functions: @@ -7,7 +7,7 @@ class Queue: Raises error if the queue is empty enqueue: Add an object to the end of the queue isEmpty: check if the queue is empty - ''' + """ def __init__(self) -> None: self.queue = [] diff --git a/Solutions/DataStructures/Stack.py b/Solutions/DataStructures/Stack.py index 80c4db4..6975ba6 100644 --- a/Solutions/DataStructures/Stack.py +++ b/Solutions/DataStructures/Stack.py @@ -1,5 +1,5 @@ class Stack: - ''' + """ Stack Class for the implementation of a stack Functions: @@ -7,7 +7,7 @@ class Stack: pop: Pop the object at the top of the stack Raises erorr if the stack is empty push: Push an object to the top of the stack - ''' + """ def __init__(self) -> None: self.stack = [] @@ -20,7 +20,7 @@ def __repr__(self) -> str: def __len__(self) -> int: return len(self.stack) - def pop(self) -> int : + def pop(self) -> int: # Pop the value at the stack top if self.rear == -1: raise Exception("Stack Underflow. Cannot pop from an empty stack") @@ -28,7 +28,7 @@ def pop(self) -> int : self.rear = -1 self.top = -1 else: - self.top -= 1 + self.top -= 1 return self.stack.pop() def push(self, val: int) -> None: diff --git a/Solutions/DataStructures/Tree.py b/Solutions/DataStructures/Tree.py index 213a1b1..7dd597d 100644 --- a/Solutions/DataStructures/Tree.py +++ b/Solutions/DataStructures/Tree.py @@ -1,5 +1,5 @@ class Node: - ''' + """ Node Class for the nodes of a Binary Tree Functions: @@ -7,7 +7,7 @@ class Node: height_helper: Helper function to calculate the height of a Binary Tree num_nodes: Helper function to calculate the number of Nodes in a Binary Tree to_str: Helper function for __repr__ - ''' + """ def __init__(self, val: int, left: int = None, right: int = None) -> None: self.val = val @@ -66,7 +66,7 @@ def to_str(self) -> str: class BinaryTree: - ''' + """ Binary Tree Class Functions: @@ -75,7 +75,7 @@ class BinaryTree: NOTE: This class does not have the add node function and nodes have to be added manually - ''' + """ def __init__(self) -> None: self.root = None @@ -83,7 +83,7 @@ def __init__(self) -> None: def __len__(self) -> int: if self.root: return self.root.num_nodes() - return 0 + return 0 def __repr__(self) -> str: return str(self.root) @@ -96,12 +96,12 @@ def find_height(self): class BinarySearchTree(BinaryTree): - ''' + """ Binary Tree Class (INHERITS FROM THE BinaryTree CLASS) Functions: add: Add nodes to a Binary Search Tree (uses insert_helper in the Node Class) - ''' + """ def __init__(self) -> None: BinaryTree.__init__(self) diff --git a/Solutions/DataStructures/Trie.py b/Solutions/DataStructures/Trie.py index b3fae0e..17556d4 100644 --- a/Solutions/DataStructures/Trie.py +++ b/Solutions/DataStructures/Trie.py @@ -2,9 +2,9 @@ class TrieNode: - ''' + """ TrieNode Class for the nodes of a Pre-processing Trie - ''' + """ def __init__(self) -> None: self.children = {} @@ -12,7 +12,7 @@ def __init__(self) -> None: class Trie: - ''' + """ Pre-processing Trie Class Functions: @@ -20,11 +20,11 @@ class Trie: add_words: Add a list of strings to the Trie get_suggestions: Get all possible words from the given prefix _traverse: Helper function for get_suggestions (generates the words from prefix) - ''' + """ def __init__(self) -> None: self.root = TrieNode() - + def add(self, word: str) -> None: # Add a string to the Trie pos = self.root