Skip to content

BST and RSA doctest #8693

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 13 commits into from
Aug 15, 2023
25 changes: 15 additions & 10 deletions ciphers/rsa_key_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
import random
import sys

from . import cryptomath_module as cryptoMath # noqa: N812
from . import rabin_miller as rabinMiller # noqa: N812
from . import cryptomath_module, rabin_miller


def main() -> None:
Expand All @@ -13,20 +12,26 @@ def main() -> None:


def generate_key(key_size: int) -> tuple[tuple[int, int], tuple[int, int]]:
print("Generating prime p...")
p = rabinMiller.generate_large_prime(key_size)
print("Generating prime q...")
q = rabinMiller.generate_large_prime(key_size)
"""
>>> random.seed(0) # for repeatability
>>> public_key, private_key = generate_key(8)
>>> public_key
(26569, 239)
>>> private_key
(26569, 2855)
"""
p = rabin_miller.generate_large_prime(key_size)
q = rabin_miller.generate_large_prime(key_size)
n = p * q

print("Generating e that is relatively prime to (p - 1) * (q - 1)...")
# Generate e that is relatively prime to (p - 1) * (q - 1)
while True:
e = random.randrange(2 ** (key_size - 1), 2 ** (key_size))
if cryptoMath.gcd(e, (p - 1) * (q - 1)) == 1:
if cryptomath_module.gcd(e, (p - 1) * (q - 1)) == 1:
break

print("Calculating d that is mod inverse of e...")
d = cryptoMath.find_mod_inverse(e, (p - 1) * (q - 1))
# Calculate d that is mod inverse of e
d = cryptomath_module.find_mod_inverse(e, (p - 1) * (q - 1))

public_key = (n, e)
private_key = (n, d)
Expand Down
123 changes: 64 additions & 59 deletions data_structures/binary_tree/binary_search_tree.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,58 @@
"""
r"""
A binary search Tree

Example
8
/ \
3 10
/ \ \
1 6 14
/ \ /
4 7 13

>>> t = BinarySearchTree()
>>> t.insert(8, 3, 6, 1, 10, 14, 13, 4, 7)
>>> print(" ".join(repr(i.value) for i in t.traversal_tree()))
8 3 1 6 4 7 10 14 13
>>> print(" ".join(repr(i.value) for i in t.traversal_tree(postorder)))
1 4 7 6 3 13 14 10 8
>>> BinarySearchTree().search(6)
Traceback (most recent call last):
...
IndexError: Warning: Tree is empty! please use another.

Other example:

>>> testlist = (8, 3, 6, 1, 10, 14, 13, 4, 7)
>>> t = BinarySearchTree()
>>> for i in testlist:
... t.insert(i)

Prints all the elements of the list in order traversal
>>> print(t)
{'8': ({'3': (1, {'6': (4, 7)})}, {'10': (None, {'14': (13, None)})})}

Test existence
>>> t.search(6) is not None
True
>>> t.search(-1) is not None
False

>>> t.search(6).is_right
True
>>> t.search(1).is_right
False

>>> t.get_max().value
14
>>> t.get_min().value
1
>>> t.empty()
False
>>> for i in testlist:
... t.remove(i)
>>> t.empty()
True
"""

from collections.abc import Iterable
Expand All @@ -20,6 +73,12 @@ def __repr__(self) -> str:
return str(self.value)
return pformat({f"{self.value}": (self.left, self.right)}, indent=1)

@property
def is_right(self) -> bool:
if self.parent and self.parent.right:
return self == self.parent.right
return False


class BinarySearchTree:
def __init__(self, root: Node | None = None):
Expand All @@ -35,18 +94,13 @@ def __reassign_nodes(self, node: Node, new_children: Node | None) -> None:
if new_children is not None: # reset its kids
new_children.parent = node.parent
if node.parent is not None: # reset its parent
if self.is_right(node): # If it is the right children
if node.is_right: # If it is the right children
node.parent.right = new_children
else:
node.parent.left = new_children
else:
self.root = None

def is_right(self, node: Node) -> bool:
if node.parent and node.parent.right:
return node == node.parent.right
return False

def empty(self) -> bool:
return self.root is None

Expand Down Expand Up @@ -128,12 +182,12 @@ def remove(self, value: int) -> None:
elif node.right is None: # Has only left children
self.__reassign_nodes(node, node.left)
else:
tmp_node = self.get_max(
predecessor = self.get_max(
node.left
) # Gets the max value of the left branch
self.remove(tmp_node.value) # type: ignore
self.remove(predecessor.value) # type: ignore
node.value = (
tmp_node.value # type: ignore
predecessor.value # type: ignore
) # Assigns the value to the node to delete and keep tree structure

def preorder_traverse(self, node: Node | None) -> Iterable:
Expand Down Expand Up @@ -177,55 +231,6 @@ def postorder(curr_node: Node | None) -> list[Node]:
return node_list


def binary_search_tree() -> None:
r"""
Example
8
/ \
3 10
/ \ \
1 6 14
/ \ /
4 7 13

>>> t = BinarySearchTree()
>>> t.insert(8, 3, 6, 1, 10, 14, 13, 4, 7)
>>> print(" ".join(repr(i.value) for i in t.traversal_tree()))
8 3 1 6 4 7 10 14 13
>>> print(" ".join(repr(i.value) for i in t.traversal_tree(postorder)))
1 4 7 6 3 13 14 10 8
>>> BinarySearchTree().search(6)
Traceback (most recent call last):
...
IndexError: Warning: Tree is empty! please use another.
"""
testlist = (8, 3, 6, 1, 10, 14, 13, 4, 7)
t = BinarySearchTree()
for i in testlist:
t.insert(i)

# Prints all the elements of the list in order traversal
print(t)

if t.search(6) is not None:
print("The value 6 exists")
else:
print("The value 6 doesn't exist")

if t.search(-1) is not None:
print("The value -1 exists")
else:
print("The value -1 doesn't exist")

if not t.empty():
print("Max Value: ", t.get_max().value) # type: ignore
print("Min Value: ", t.get_min().value) # type: ignore

for i in testlist:
t.remove(i)
print(t)


if __name__ == "__main__":
import doctest

Expand Down