diff --git a/DIRECTORY.md b/DIRECTORY.md index b0ba3c385..c199a4329 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -50,6 +50,7 @@ * [Index Of Rightmost Set Bit](bit_manipulation/index_of_rightmost_set_bit.py) * [Is Even](bit_manipulation/is_even.py) * [Is Power Of Two](bit_manipulation/is_power_of_two.py) + * [Largest Pow Of Two Le Num](bit_manipulation/largest_pow_of_two_le_num.py) * [Missing Number](bit_manipulation/missing_number.py) * [Numbers Different Signs](bit_manipulation/numbers_different_signs.py) * [Reverse Bits](bit_manipulation/reverse_bits.py) @@ -322,6 +323,7 @@ * [Integer Partition](dynamic_programming/integer_partition.py) * [Iterating Through Submasks](dynamic_programming/iterating_through_submasks.py) * [Knapsack](dynamic_programming/knapsack.py) + * [Largest Divisible Subset](dynamic_programming/largest_divisible_subset.py) * [Longest Common Subsequence](dynamic_programming/longest_common_subsequence.py) * [Longest Common Substring](dynamic_programming/longest_common_substring.py) * [Longest Increasing Subsequence](dynamic_programming/longest_increasing_subsequence.py) @@ -460,6 +462,7 @@ ## Greedy Methods * [Fractional Knapsack](greedy_methods/fractional_knapsack.py) * [Fractional Knapsack 2](greedy_methods/fractional_knapsack_2.py) + * [Gas Station](greedy_methods/gas_station.py) * [Minimum Waiting Time](greedy_methods/minimum_waiting_time.py) * [Optimal Merge Pattern](greedy_methods/optimal_merge_pattern.py) @@ -542,6 +545,7 @@ * [Average Median](maths/average_median.py) * [Average Mode](maths/average_mode.py) * [Bailey Borwein Plouffe](maths/bailey_borwein_plouffe.py) + * [Base Neg2 Conversion](maths/base_neg2_conversion.py) * [Basic Maths](maths/basic_maths.py) * [Bell Numbers](maths/bell_numbers.py) * [Binary Exp Mod](maths/binary_exp_mod.py) @@ -657,7 +661,6 @@ * [P Series](maths/series/p_series.py) * [Sieve Of Eratosthenes](maths/sieve_of_eratosthenes.py) * [Sigmoid](maths/sigmoid.py) - * [Sigmoid Linear Unit](maths/sigmoid_linear_unit.py) * [Signum](maths/signum.py) * [Simpson Rule](maths/simpson_rule.py) * [Simultaneous Linear Equation Solver](maths/simultaneous_linear_equation_solver.py) @@ -716,6 +719,7 @@ * [Leaky Rectified Linear Unit](neural_network/activation_functions/leaky_rectified_linear_unit.py) * [Rectified Linear Unit](neural_network/activation_functions/rectified_linear_unit.py) * [Scaled Exponential Linear Unit](neural_network/activation_functions/scaled_exponential_linear_unit.py) + * [Sigmoid Linear Unit](neural_network/activation_functions/sigmoid_linear_unit.py) * [Back Propagation Neural Network](neural_network/back_propagation_neural_network.py) * [Convolution Neural Network](neural_network/convolution_neural_network.py) * [Perceptron](neural_network/perceptron.py) @@ -1180,6 +1184,7 @@ * [Naive String Search](strings/naive_string_search.py) * [Ngram](strings/ngram.py) * [Palindrome](strings/palindrome.py) + * [Pig Latin](strings/pig_latin.py) * [Prefix Function](strings/prefix_function.py) * [Rabin Karp](strings/rabin_karp.py) * [Remove Duplicate](strings/remove_duplicate.py) diff --git a/data_structures/linked_list/print_reverse.py b/data_structures/linked_list/print_reverse.py index f83d5607f..a023745de 100644 --- a/data_structures/linked_list/print_reverse.py +++ b/data_structures/linked_list/print_reverse.py @@ -1,22 +1,91 @@ from __future__ import annotations +from collections.abc import Iterable, Iterator +from dataclasses import dataclass + +@dataclass class Node: - def __init__(self, data=None): - self.data = data - self.next = None - - def __repr__(self): - """Returns a visual representation of the node and all its following nodes.""" - string_rep = [] - temp = self - while temp: - string_rep.append(f"{temp.data}") - temp = temp.next - return "->".join(string_rep) + data: int + next_node: Node | None = None -def make_linked_list(elements_list: list): +class LinkedList: + """A class to represent a Linked List. + Use a tail pointer to speed up the append() operation. + """ + + def __init__(self) -> None: + """Initialize a LinkedList with the head node set to None. + >>> linked_list = LinkedList() + >>> (linked_list.head, linked_list.tail) + (None, None) + """ + self.head: Node | None = None + self.tail: Node | None = None # Speeds up the append() operation + + def __iter__(self) -> Iterator[int]: + """Iterate the LinkedList yielding each Node's data. + >>> linked_list = LinkedList() + >>> items = (1, 2, 3, 4, 5) + >>> linked_list.extend(items) + >>> tuple(linked_list) == items + True + """ + node = self.head + while node: + yield node.data + node = node.next_node + + def __repr__(self) -> str: + """Returns a string representation of the LinkedList. + >>> linked_list = LinkedList() + >>> str(linked_list) + '' + >>> linked_list.append(1) + >>> str(linked_list) + '1' + >>> linked_list.extend([2, 3, 4, 5]) + >>> str(linked_list) + '1 -> 2 -> 3 -> 4 -> 5' + """ + return " -> ".join([str(data) for data in self]) + + def append(self, data: int) -> None: + """Appends a new node with the given data to the end of the LinkedList. + >>> linked_list = LinkedList() + >>> str(linked_list) + '' + >>> linked_list.append(1) + >>> str(linked_list) + '1' + >>> linked_list.append(2) + >>> str(linked_list) + '1 -> 2' + """ + if self.tail: + self.tail.next_node = self.tail = Node(data) + else: + self.head = self.tail = Node(data) + + def extend(self, items: Iterable[int]) -> None: + """Appends each item to the end of the LinkedList. + >>> linked_list = LinkedList() + >>> linked_list.extend([]) + >>> str(linked_list) + '' + >>> linked_list.extend([1, 2]) + >>> str(linked_list) + '1 -> 2' + >>> linked_list.extend([3,4]) + >>> str(linked_list) + '1 -> 2 -> 3 -> 4' + """ + for item in items: + self.append(item) + + +def make_linked_list(elements_list: Iterable[int]) -> LinkedList: """Creates a Linked List from the elements of the given sequence (list/tuple) and returns the head of the Linked List. >>> make_linked_list([]) @@ -28,43 +97,30 @@ def make_linked_list(elements_list: list): >>> make_linked_list(['abc']) abc >>> make_linked_list([7, 25]) - 7->25 + 7 -> 25 """ if not elements_list: raise Exception("The Elements List is empty") - current = head = Node(elements_list[0]) - for i in range(1, len(elements_list)): - current.next = Node(elements_list[i]) - current = current.next - return head + linked_list = LinkedList() + linked_list.extend(elements_list) + return linked_list -def print_reverse(head_node: Node) -> None: +def in_reverse(linked_list: LinkedList) -> str: """Prints the elements of the given Linked List in reverse order - >>> print_reverse([]) - >>> linked_list = make_linked_list([69, 88, 73]) - >>> print_reverse(linked_list) - 73 - 88 - 69 + >>> in_reverse(LinkedList()) + '' + >>> in_reverse(make_linked_list([69, 88, 73])) + '73 <- 88 <- 69' """ - if head_node is not None and isinstance(head_node, Node): - print_reverse(head_node.next) - print(head_node.data) - - -def main(): - from doctest import testmod - - testmod() - - linked_list = make_linked_list([14, 52, 14, 12, 43]) - print("Linked List:") - print(linked_list) - print("Elements in Reverse:") - print_reverse(linked_list) + return " <- ".join(str(line) for line in reversed(tuple(linked_list))) if __name__ == "__main__": - main() + from doctest import testmod + + testmod() + linked_list = make_linked_list((14, 52, 14, 12, 43)) + print(f"Linked List: {linked_list}") + print(f"Reverse List: {in_reverse(linked_list)}")