Skip to content

[pull] master from TheAlgorithms:master #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@
* [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)
* [Longest Increasing Subsequence O(Nlogn)](dynamic_programming/longest_increasing_subsequence_o(nlogn).py)
* [Longest Increasing Subsequence O Nlogn](dynamic_programming/longest_increasing_subsequence_o_nlogn.py)
* [Longest Palindromic Subsequence](dynamic_programming/longest_palindromic_subsequence.py)
* [Matrix Chain Multiplication](dynamic_programming/matrix_chain_multiplication.py)
* [Matrix Chain Order](dynamic_programming/matrix_chain_order.py)
Expand Down Expand Up @@ -465,7 +465,7 @@
* [Dijkstra Alternate](graphs/dijkstra_alternate.py)
* [Dijkstra Binary Grid](graphs/dijkstra_binary_grid.py)
* [Dinic](graphs/dinic.py)
* [Directed And Undirected (Weighted) Graph](graphs/directed_and_undirected_(weighted)_graph.py)
* [Directed And Undirected Weighted Graph](graphs/directed_and_undirected_weighted_graph.py)
* [Edmonds Karp Multiple Source And Sink](graphs/edmonds_karp_multiple_source_and_sink.py)
* [Eulerian Path And Circuit For Undirected Graph](graphs/eulerian_path_and_circuit_for_undirected_graph.py)
* [Even Tree](graphs/even_tree.py)
Expand Down Expand Up @@ -792,7 +792,6 @@
* [Minimum Cut](networking_flow/minimum_cut.py)

## Neural Network
* [2 Hidden Layers Neural Network](neural_network/2_hidden_layers_neural_network.py)
* Activation Functions
* [Binary Step](neural_network/activation_functions/binary_step.py)
* [Exponential Linear Unit](neural_network/activation_functions/exponential_linear_unit.py)
Expand All @@ -809,6 +808,7 @@
* [Convolution Neural Network](neural_network/convolution_neural_network.py)
* [Input Data](neural_network/input_data.py)
* [Simple Neural Network](neural_network/simple_neural_network.py)
* [Two Hidden Layers Neural Network](neural_network/two_hidden_layers_neural_network.py)

## Other
* [Activity Selection](other/activity_selection.py)
Expand Down
5 changes: 2 additions & 3 deletions backtracking/crossword_puzzle_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ def is_valid(
if vertical:
if row + i >= len(puzzle) or puzzle[row + i][col] != "":
return False
else:
if col + i >= len(puzzle[0]) or puzzle[row][col + i] != "":
return False
elif col + i >= len(puzzle[0]) or puzzle[row][col + i] != "":
return False
return True


Expand Down
5 changes: 2 additions & 3 deletions cellular_automata/game_of_life.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,8 @@ def __judge_point(pt: bool, neighbours: list[list[bool]]) -> bool:
state = True
elif alive > 3:
state = False
else:
if alive == 3:
state = True
elif alive == 3:
state = True

return state

Expand Down
21 changes: 10 additions & 11 deletions ciphers/decrypt_caesar_with_chi_squared.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,20 +206,19 @@ def decrypt_caesar_with_chi_squared(

# Add the margin of error to the total chi squared statistic
chi_squared_statistic += chi_letter_value
else:
if letter.lower() in frequencies:
# Get the amount of times the letter occurs in the message
occurrences = decrypted_with_shift.count(letter)
elif letter.lower() in frequencies:
# Get the amount of times the letter occurs in the message
occurrences = decrypted_with_shift.count(letter)

# Get the excepcted amount of times the letter should appear based
# on letter frequencies
expected = frequencies[letter] * occurrences
# Get the excepcted amount of times the letter should appear based
# on letter frequencies
expected = frequencies[letter] * occurrences

# Complete the chi squared statistic formula
chi_letter_value = ((occurrences - expected) ** 2) / expected
# Complete the chi squared statistic formula
chi_letter_value = ((occurrences - expected) ** 2) / expected

# Add the margin of error to the total chi squared statistic
chi_squared_statistic += chi_letter_value
# Add the margin of error to the total chi squared statistic
chi_squared_statistic += chi_letter_value

# Add the data to the chi_squared_statistic_values dictionary
chi_squared_statistic_values[shift] = (
Expand Down
38 changes: 18 additions & 20 deletions ciphers/hill_cipher.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

import string

import numpy
import numpy as np

from maths.greatest_common_divisor import greatest_common_divisor

Expand All @@ -49,11 +49,11 @@ class HillCipher:
# i.e. a total of 36 characters

# take x and return x % len(key_string)
modulus = numpy.vectorize(lambda x: x % 36)
modulus = np.vectorize(lambda x: x % 36)

to_int = numpy.vectorize(round)
to_int = np.vectorize(round)

def __init__(self, encrypt_key: numpy.ndarray) -> None:
def __init__(self, encrypt_key: np.ndarray) -> None:
"""
encrypt_key is an NxN numpy array
"""
Expand All @@ -63,7 +63,7 @@ def __init__(self, encrypt_key: numpy.ndarray) -> None:

def replace_letters(self, letter: str) -> int:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.replace_letters('T')
19
>>> hill_cipher.replace_letters('0')
Expand All @@ -73,7 +73,7 @@ def replace_letters(self, letter: str) -> int:

def replace_digits(self, num: int) -> str:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.replace_digits(19)
'T'
>>> hill_cipher.replace_digits(26)
Expand All @@ -83,10 +83,10 @@ def replace_digits(self, num: int) -> str:

def check_determinant(self) -> None:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.check_determinant()
"""
det = round(numpy.linalg.det(self.encrypt_key))
det = round(np.linalg.det(self.encrypt_key))

if det < 0:
det = det % len(self.key_string)
Expand All @@ -101,7 +101,7 @@ def check_determinant(self) -> None:

def process_text(self, text: str) -> str:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.process_text('Testing Hill Cipher')
'TESTINGHILLCIPHERR'
>>> hill_cipher.process_text('hello')
Expand All @@ -117,7 +117,7 @@ def process_text(self, text: str) -> str:

def encrypt(self, text: str) -> str:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.encrypt('testing hill cipher')
'WHXYJOLM9C6XT085LL'
>>> hill_cipher.encrypt('hello')
Expand All @@ -129,7 +129,7 @@ def encrypt(self, text: str) -> str:
for i in range(0, len(text) - self.break_key + 1, self.break_key):
batch = text[i : i + self.break_key]
vec = [self.replace_letters(char) for char in batch]
batch_vec = numpy.array([vec]).T
batch_vec = np.array([vec]).T
batch_encrypted = self.modulus(self.encrypt_key.dot(batch_vec)).T.tolist()[
0
]
Expand All @@ -140,14 +140,14 @@ def encrypt(self, text: str) -> str:

return encrypted

def make_decrypt_key(self) -> numpy.ndarray:
def make_decrypt_key(self) -> np.ndarray:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.make_decrypt_key()
array([[ 6, 25],
[ 5, 26]])
"""
det = round(numpy.linalg.det(self.encrypt_key))
det = round(np.linalg.det(self.encrypt_key))

if det < 0:
det = det % len(self.key_string)
Expand All @@ -158,16 +158,14 @@ def make_decrypt_key(self) -> numpy.ndarray:
break

inv_key = (
det_inv
* numpy.linalg.det(self.encrypt_key)
* numpy.linalg.inv(self.encrypt_key)
det_inv * np.linalg.det(self.encrypt_key) * np.linalg.inv(self.encrypt_key)
)

return self.to_int(self.modulus(inv_key))

def decrypt(self, text: str) -> str:
"""
>>> hill_cipher = HillCipher(numpy.array([[2, 5], [1, 6]]))
>>> hill_cipher = HillCipher(np.array([[2, 5], [1, 6]]))
>>> hill_cipher.decrypt('WHXYJOLM9C6XT085LL')
'TESTINGHILLCIPHERR'
>>> hill_cipher.decrypt('85FF00')
Expand All @@ -180,7 +178,7 @@ def decrypt(self, text: str) -> str:
for i in range(0, len(text) - self.break_key + 1, self.break_key):
batch = text[i : i + self.break_key]
vec = [self.replace_letters(char) for char in batch]
batch_vec = numpy.array([vec]).T
batch_vec = np.array([vec]).T
batch_decrypted = self.modulus(decrypt_key.dot(batch_vec)).T.tolist()[0]
decrypted_batch = "".join(
self.replace_digits(num) for num in batch_decrypted
Expand All @@ -199,7 +197,7 @@ def main() -> None:
row = [int(x) for x in input().split()]
hill_matrix.append(row)

hc = HillCipher(numpy.array(hill_matrix))
hc = HillCipher(np.array(hill_matrix))

print("Would you like to encrypt or decrypt some text? (1 or 2)")
option = input("\n1. Encrypt\n2. Decrypt\n")
Expand Down
10 changes: 5 additions & 5 deletions data_structures/binary_tree/avl_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,11 +215,11 @@ def del_node(root: MyNode, data: Any) -> MyNode | None:
return root
else:
root.set_left(del_node(left_child, data))
else: # root.get_data() < data
if right_child is None:
return root
else:
root.set_right(del_node(right_child, data))
# root.get_data() < data
elif right_child is None:
return root
else:
root.set_right(del_node(right_child, data))

if get_height(right_child) - get_height(left_child) == 2:
assert right_child is not None
Expand Down
9 changes: 4 additions & 5 deletions data_structures/binary_tree/binary_search_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,12 +185,11 @@ def __insert(self, value) -> None:
break
else:
parent_node = parent_node.left
elif parent_node.right is None:
parent_node.right = new_node
break
else:
if parent_node.right is None:
parent_node.right = new_node
break
else:
parent_node = parent_node.right
parent_node = parent_node.right
new_node.parent = parent_node

def insert(self, *values) -> Self:
Expand Down
22 changes: 10 additions & 12 deletions data_structures/binary_tree/binary_search_tree_recursive.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,13 @@ def put(self, label: int) -> None:
def _put(self, node: Node | None, label: int, parent: Node | None = None) -> Node:
if node is None:
node = Node(label, parent)
elif label < node.label:
node.left = self._put(node.left, label, node)
elif label > node.label:
node.right = self._put(node.right, label, node)
else:
if label < node.label:
node.left = self._put(node.left, label, node)
elif label > node.label:
node.right = self._put(node.right, label, node)
else:
msg = f"Node with label {label} already exists"
raise ValueError(msg)
msg = f"Node with label {label} already exists"
raise ValueError(msg)

return node

Expand All @@ -106,11 +105,10 @@ def _search(self, node: Node | None, label: int) -> Node:
if node is None:
msg = f"Node with label {label} does not exist"
raise ValueError(msg)
else:
if label < node.label:
node = self._search(node.left, label)
elif label > node.label:
node = self._search(node.right, label)
elif label < node.label:
node = self._search(node.left, label)
elif label > node.label:
node = self._search(node.right, label)

return node

Expand Down
14 changes: 13 additions & 1 deletion data_structures/binary_tree/binary_tree_traversals.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ def level_order(root: Node | None) -> Generator[int, None, None]:
"""
Returns a list of nodes value from a whole binary tree in Level Order Traverse.
Level Order traverse: Visit nodes of the tree level-by-level.
>>> list(level_order(make_tree()))
[1, 2, 3, 4, 5]
"""

if root is None:
Expand All @@ -120,6 +122,10 @@ def get_nodes_from_left_to_right(
"""
Returns a list of nodes value from a particular level:
Left to right direction of the binary tree.
>>> list(get_nodes_from_left_to_right(make_tree(), 1))
[1]
>>> list(get_nodes_from_left_to_right(make_tree(), 2))
[2, 3]
"""

def populate_output(root: Node | None, level: int) -> Generator[int, None, None]:
Expand All @@ -140,10 +146,14 @@ def get_nodes_from_right_to_left(
"""
Returns a list of nodes value from a particular level:
Right to left direction of the binary tree.
>>> list(get_nodes_from_right_to_left(make_tree(), 1))
[1]
>>> list(get_nodes_from_right_to_left(make_tree(), 2))
[3, 2]
"""

def populate_output(root: Node | None, level: int) -> Generator[int, None, None]:
if root is None:
if not root:
return
if level == 1:
yield root.data
Expand All @@ -158,6 +168,8 @@ def zigzag(root: Node | None) -> Generator[int, None, None]:
"""
ZigZag traverse:
Returns a list of nodes value from left to right and right to left, alternatively.
>>> list(zigzag(make_tree()))
[1, 3, 2, 4, 5]
"""
if root is None:
return
Expand Down
Loading