mirror of
https://github.com/TheAlgorithms/Python.git
synced 2025-02-07 10:00:55 +00:00
Merge remote-tracking branch 'origin/naive-bayes-text-classifier' into naive-bayes-text-classifier
This commit is contained in:
commit
9d19489c1f
|
@ -1,5 +1,5 @@
|
|||
# https://github.com/microsoft/vscode-dev-containers/blob/main/containers/python-3/README.md
|
||||
ARG VARIANT=3.11-bookworm
|
||||
ARG VARIANT=3.12-bookworm
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/python:${VARIANT}
|
||||
COPY requirements.txt /tmp/pip-tmp/
|
||||
RUN python3 -m pip install --upgrade pip \
|
||||
|
|
1
.devcontainer/README.md
Normal file
1
.devcontainer/README.md
Normal file
|
@ -0,0 +1 @@
|
|||
https://code.visualstudio.com/docs/devcontainers/tutorial
|
|
@ -4,10 +4,10 @@
|
|||
"dockerfile": "Dockerfile",
|
||||
"context": "..",
|
||||
"args": {
|
||||
// Update 'VARIANT' to pick a Python version: 3, 3.10, 3.9, 3.8, 3.7, 3.6
|
||||
// Update 'VARIANT' to pick a Python version: 3, 3.11, 3.10, 3.9, 3.8
|
||||
// Append -bullseye or -buster to pin to an OS version.
|
||||
// Use -bullseye variants on local on arm64/Apple Silicon.
|
||||
"VARIANT": "3.11-bookworm",
|
||||
"VARIANT": "3.12-bookworm",
|
||||
}
|
||||
},
|
||||
|
||||
|
|
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
|
@ -69,7 +69,7 @@
|
|||
|
||||
# /other/ @cclauss # TODO: Uncomment this line after Hacktoberfest
|
||||
|
||||
/project_euler/ @dhruvmanila
|
||||
# /project_euler/
|
||||
|
||||
# /quantum/
|
||||
|
||||
|
|
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
|
@ -9,10 +9,11 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.11
|
||||
python-version: 3.12
|
||||
allow-prereleases: true
|
||||
- uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
|
|
4
.github/workflows/ruff.yml
vendored
4
.github/workflows/ruff.yml
vendored
|
@ -11,6 +11,6 @@ jobs:
|
|||
ruff:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- run: pip install --user ruff
|
||||
- run: ruff --format=github .
|
||||
- run: ruff --output-format=github .
|
||||
|
|
|
@ -16,7 +16,7 @@ repos:
|
|||
- id: auto-walrus
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.0.291
|
||||
rev: v0.0.292
|
||||
hooks:
|
||||
- id: ruff
|
||||
|
||||
|
@ -33,7 +33,7 @@ repos:
|
|||
- tomli
|
||||
|
||||
- repo: https://github.com/tox-dev/pyproject-fmt
|
||||
rev: "1.1.0"
|
||||
rev: "1.2.0"
|
||||
hooks:
|
||||
- id: pyproject-fmt
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ pre-commit run --all-files --show-diff-on-failure
|
|||
|
||||
We want your work to be readable by others; therefore, we encourage you to note the following:
|
||||
|
||||
- Please write in Python 3.11+. For instance: `print()` is a function in Python 3 so `print "Hello"` will *not* work but `print("Hello")` will.
|
||||
- Please write in Python 3.12+. For instance: `print()` is a function in Python 3 so `print "Hello"` will *not* work but `print("Hello")` will.
|
||||
- Please focus hard on the naming of functions, classes, and variables. Help your reader by using __descriptive names__ that can help you to remove redundant comments.
|
||||
- Single letter variable names are *old school* so please avoid them unless their life only spans a few lines.
|
||||
- Expand acronyms because `gcd()` is hard to understand but `greatest_common_divisor()` is not.
|
||||
|
|
29
DIRECTORY.md
29
DIRECTORY.md
|
@ -26,7 +26,6 @@
|
|||
* [Hamiltonian Cycle](backtracking/hamiltonian_cycle.py)
|
||||
* [Knight Tour](backtracking/knight_tour.py)
|
||||
* [Minimax](backtracking/minimax.py)
|
||||
* [Minmax](backtracking/minmax.py)
|
||||
* [N Queens](backtracking/n_queens.py)
|
||||
* [N Queens Math](backtracking/n_queens_math.py)
|
||||
* [Power Sum](backtracking/power_sum.py)
|
||||
|
@ -51,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)
|
||||
* [Missing Number](bit_manipulation/missing_number.py)
|
||||
* [Numbers Different Signs](bit_manipulation/numbers_different_signs.py)
|
||||
* [Reverse Bits](bit_manipulation/reverse_bits.py)
|
||||
* [Single Bit Manipulation Operations](bit_manipulation/single_bit_manipulation_operations.py)
|
||||
|
@ -132,7 +132,6 @@
|
|||
* [Run Length Encoding](compression/run_length_encoding.py)
|
||||
|
||||
## Computer Vision
|
||||
* [Cnn Classification](computer_vision/cnn_classification.py)
|
||||
* [Flip Augmentation](computer_vision/flip_augmentation.py)
|
||||
* [Haralick Descriptors](computer_vision/haralick_descriptors.py)
|
||||
* [Harris Corner](computer_vision/harris_corner.py)
|
||||
|
@ -232,6 +231,8 @@
|
|||
* [Merge Two Lists](data_structures/linked_list/merge_two_lists.py)
|
||||
* [Middle Element Of Linked List](data_structures/linked_list/middle_element_of_linked_list.py)
|
||||
* [Print Reverse](data_structures/linked_list/print_reverse.py)
|
||||
* [Reverse K Group](data_structures/linked_list/reverse_k_group.py)
|
||||
* [Rotate To The Right](data_structures/linked_list/rotate_to_the_right.py)
|
||||
* [Singly Linked List](data_structures/linked_list/singly_linked_list.py)
|
||||
* [Skip List](data_structures/linked_list/skip_list.py)
|
||||
* [Swap Nodes](data_structures/linked_list/swap_nodes.py)
|
||||
|
@ -318,7 +319,6 @@
|
|||
* [Floyd Warshall](dynamic_programming/floyd_warshall.py)
|
||||
* [Integer Partition](dynamic_programming/integer_partition.py)
|
||||
* [Iterating Through Submasks](dynamic_programming/iterating_through_submasks.py)
|
||||
* [K Means Clustering Tensorflow](dynamic_programming/k_means_clustering_tensorflow.py)
|
||||
* [Knapsack](dynamic_programming/knapsack.py)
|
||||
* [Longest Common Subsequence](dynamic_programming/longest_common_subsequence.py)
|
||||
* [Longest Common Substring](dynamic_programming/longest_common_substring.py)
|
||||
|
@ -341,6 +341,7 @@
|
|||
* [Palindrome Partitioning](dynamic_programming/palindrome_partitioning.py)
|
||||
* [Regex Match](dynamic_programming/regex_match.py)
|
||||
* [Rod Cutting](dynamic_programming/rod_cutting.py)
|
||||
* [Smith Waterman](dynamic_programming/smith_waterman.py)
|
||||
* [Subset Generation](dynamic_programming/subset_generation.py)
|
||||
* [Sum Of Subset](dynamic_programming/sum_of_subset.py)
|
||||
* [Tribonacci](dynamic_programming/tribonacci.py)
|
||||
|
@ -380,9 +381,6 @@
|
|||
* [Mandelbrot](fractals/mandelbrot.py)
|
||||
* [Sierpinski Triangle](fractals/sierpinski_triangle.py)
|
||||
|
||||
## Fuzzy Logic
|
||||
* [Fuzzy Operations](fuzzy_logic/fuzzy_operations.py)
|
||||
|
||||
## Genetic Algorithm
|
||||
* [Basic String](genetic_algorithm/basic_string.py)
|
||||
|
||||
|
@ -513,8 +511,6 @@
|
|||
* Local Weighted Learning
|
||||
* [Local Weighted Learning](machine_learning/local_weighted_learning/local_weighted_learning.py)
|
||||
* [Logistic Regression](machine_learning/logistic_regression.py)
|
||||
* Lstm
|
||||
* [Lstm Prediction](machine_learning/lstm/lstm_prediction.py)
|
||||
* [Mfcc](machine_learning/mfcc.py)
|
||||
* [Multilayer Perceptron Classifier](machine_learning/multilayer_perceptron_classifier.py)
|
||||
* [Polynomial Regression](machine_learning/polynomial_regression.py)
|
||||
|
@ -529,7 +525,6 @@
|
|||
|
||||
## Maths
|
||||
* [Abs](maths/abs.py)
|
||||
* [Add](maths/add.py)
|
||||
* [Addition Without Arithmetic](maths/addition_without_arithmetic.py)
|
||||
* [Aliquot Sum](maths/aliquot_sum.py)
|
||||
* [Allocation Number](maths/allocation_number.py)
|
||||
|
@ -567,7 +562,6 @@
|
|||
* [Dual Number Automatic Differentiation](maths/dual_number_automatic_differentiation.py)
|
||||
* [Entropy](maths/entropy.py)
|
||||
* [Euclidean Distance](maths/euclidean_distance.py)
|
||||
* [Euclidean Gcd](maths/euclidean_gcd.py)
|
||||
* [Euler Method](maths/euler_method.py)
|
||||
* [Euler Modified](maths/euler_modified.py)
|
||||
* [Eulers Totient](maths/eulers_totient.py)
|
||||
|
@ -611,7 +605,6 @@
|
|||
* [Matrix Exponentiation](maths/matrix_exponentiation.py)
|
||||
* [Max Sum Sliding Window](maths/max_sum_sliding_window.py)
|
||||
* [Median Of Two Arrays](maths/median_of_two_arrays.py)
|
||||
* [Miller Rabin](maths/miller_rabin.py)
|
||||
* [Mobius Function](maths/mobius_function.py)
|
||||
* [Modular Exponential](maths/modular_exponential.py)
|
||||
* [Monte Carlo](maths/monte_carlo.py)
|
||||
|
@ -677,6 +670,7 @@
|
|||
* [Sylvester Sequence](maths/sylvester_sequence.py)
|
||||
* [Tanh](maths/tanh.py)
|
||||
* [Test Prime Check](maths/test_prime_check.py)
|
||||
* [Three Sum](maths/three_sum.py)
|
||||
* [Trapezoidal Rule](maths/trapezoidal_rule.py)
|
||||
* [Triplet Sum](maths/triplet_sum.py)
|
||||
* [Twin Prime](maths/twin_prime.py)
|
||||
|
@ -747,6 +741,7 @@
|
|||
* [Scoring Algorithm](other/scoring_algorithm.py)
|
||||
* [Sdes](other/sdes.py)
|
||||
* [Tower Of Hanoi](other/tower_of_hanoi.py)
|
||||
* [Word Search](other/word_search.py)
|
||||
|
||||
## Physics
|
||||
* [Altitude Pressure](physics/altitude_pressure.py)
|
||||
|
@ -1067,17 +1062,7 @@
|
|||
* [Sol1](project_euler/problem_800/sol1.py)
|
||||
|
||||
## Quantum
|
||||
* [Bb84](quantum/bb84.py)
|
||||
* [Deutsch Jozsa](quantum/deutsch_jozsa.py)
|
||||
* [Half Adder](quantum/half_adder.py)
|
||||
* [Not Gate](quantum/not_gate.py)
|
||||
* [Q Fourier Transform](quantum/q_fourier_transform.py)
|
||||
* [Q Full Adder](quantum/q_full_adder.py)
|
||||
* [Quantum Entanglement](quantum/quantum_entanglement.py)
|
||||
* [Quantum Teleportation](quantum/quantum_teleportation.py)
|
||||
* [Ripple Adder Classic](quantum/ripple_adder_classic.py)
|
||||
* [Single Qubit Measure](quantum/single_qubit_measure.py)
|
||||
* [Superdense Coding](quantum/superdense_coding.py)
|
||||
|
||||
## Scheduling
|
||||
* [First Come First Served](scheduling/first_come_first_served.py)
|
||||
|
@ -1140,8 +1125,6 @@
|
|||
* [Quick Sort](sorts/quick_sort.py)
|
||||
* [Quick Sort 3 Partition](sorts/quick_sort_3_partition.py)
|
||||
* [Radix Sort](sorts/radix_sort.py)
|
||||
* [Random Normal Distribution Quicksort](sorts/random_normal_distribution_quicksort.py)
|
||||
* [Random Pivot Quick Sort](sorts/random_pivot_quick_sort.py)
|
||||
* [Recursive Bubble Sort](sorts/recursive_bubble_sort.py)
|
||||
* [Recursive Insertion Sort](sorts/recursive_insertion_sort.py)
|
||||
* [Recursive Mergesort Array](sorts/recursive_mergesort_array.py)
|
||||
|
|
|
@ -47,7 +47,7 @@ def combination_sum(candidates: list, target: int) -> list:
|
|||
>>> combination_sum([-8, 2.3, 0], 1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
RecursionError: maximum recursion depth exceeded in comparison
|
||||
RecursionError: maximum recursion depth exceeded
|
||||
"""
|
||||
path = [] # type: list[int]
|
||||
answer = [] # type: list[int]
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
"""
|
||||
Minimax helps to achieve maximum score in a game by checking all possible moves.
|
||||
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import math
|
||||
|
||||
|
||||
def minimax(
|
||||
depth: int, node_index: int, is_max: bool, scores: list[int], height: float
|
||||
) -> int:
|
||||
"""
|
||||
depth is current depth in game tree.
|
||||
node_index is index of current node in scores[].
|
||||
scores[] contains the leaves of game tree.
|
||||
height is maximum height of game tree.
|
||||
|
||||
>>> scores = [90, 23, 6, 33, 21, 65, 123, 34423]
|
||||
>>> height = math.log(len(scores), 2)
|
||||
>>> minimax(0, 0, True, scores, height)
|
||||
65
|
||||
>>> minimax(-1, 0, True, scores, height)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Depth cannot be less than 0
|
||||
>>> minimax(0, 0, True, [], 2)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: Scores cannot be empty
|
||||
>>> scores = [3, 5, 2, 9, 12, 5, 23, 23]
|
||||
>>> height = math.log(len(scores), 2)
|
||||
>>> minimax(0, 0, True, scores, height)
|
||||
12
|
||||
"""
|
||||
|
||||
if depth < 0:
|
||||
raise ValueError("Depth cannot be less than 0")
|
||||
|
||||
if not scores:
|
||||
raise ValueError("Scores cannot be empty")
|
||||
|
||||
if depth == height:
|
||||
return scores[node_index]
|
||||
|
||||
return (
|
||||
max(
|
||||
minimax(depth + 1, node_index * 2, False, scores, height),
|
||||
minimax(depth + 1, node_index * 2 + 1, False, scores, height),
|
||||
)
|
||||
if is_max
|
||||
else min(
|
||||
minimax(depth + 1, node_index * 2, True, scores, height),
|
||||
minimax(depth + 1, node_index * 2 + 1, True, scores, height),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
scores = [90, 23, 6, 33, 21, 65, 123, 34423]
|
||||
height = math.log(len(scores), 2)
|
||||
print(f"Optimal value : {minimax(0, 0, True, scores, height)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
main()
|
21
bit_manipulation/missing_number.py
Normal file
21
bit_manipulation/missing_number.py
Normal file
|
@ -0,0 +1,21 @@
|
|||
def find_missing_number(nums: list[int]) -> int:
|
||||
"""
|
||||
Finds the missing number in a list of consecutive integers.
|
||||
|
||||
Args:
|
||||
nums: A list of integers.
|
||||
|
||||
Returns:
|
||||
The missing number.
|
||||
|
||||
Example:
|
||||
>>> find_missing_number([0, 1, 3, 4])
|
||||
2
|
||||
"""
|
||||
n = len(nums)
|
||||
missing_number = n
|
||||
|
||||
for i in range(n):
|
||||
missing_number ^= i ^ nums[i]
|
||||
|
||||
return missing_number
|
|
@ -10,7 +10,7 @@ def permute_recursive(nums: list[int]) -> list[list[int]]:
|
|||
return [[]]
|
||||
for _ in range(len(nums)):
|
||||
n = nums.pop(0)
|
||||
permutations = permute_recursive(nums)
|
||||
permutations = permute_recursive(nums.copy())
|
||||
for perm in permutations:
|
||||
perm.append(n)
|
||||
result.extend(permutations)
|
||||
|
@ -43,6 +43,6 @@ def permute_backtrack(nums: list[int]) -> list[list[int]]:
|
|||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
res = permute_backtrack([1, 2, 3])
|
||||
print(res)
|
||||
result = permute_backtrack([1, 2, 3])
|
||||
print(result)
|
||||
doctest.testmod()
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
# https://en.wikipedia.org/wiki/Tree_traversal
|
||||
from __future__ import annotations
|
||||
|
||||
from collections import deque
|
||||
from collections.abc import Sequence
|
||||
from collections.abc import Generator
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
|
||||
# https://en.wikipedia.org/wiki/Tree_traversal
|
||||
@dataclass
|
||||
class Node:
|
||||
data: int
|
||||
|
@ -31,44 +30,56 @@ def make_tree() -> Node | None:
|
|||
return tree
|
||||
|
||||
|
||||
def preorder(root: Node | None) -> list[int]:
|
||||
def preorder(root: Node | None) -> Generator[int, None, None]:
|
||||
"""
|
||||
Pre-order traversal visits root node, left subtree, right subtree.
|
||||
>>> preorder(make_tree())
|
||||
>>> list(preorder(make_tree()))
|
||||
[1, 2, 4, 5, 3]
|
||||
"""
|
||||
return [root.data, *preorder(root.left), *preorder(root.right)] if root else []
|
||||
if not root:
|
||||
return
|
||||
yield root.data
|
||||
yield from preorder(root.left)
|
||||
yield from preorder(root.right)
|
||||
|
||||
|
||||
def postorder(root: Node | None) -> list[int]:
|
||||
def postorder(root: Node | None) -> Generator[int, None, None]:
|
||||
"""
|
||||
Post-order traversal visits left subtree, right subtree, root node.
|
||||
>>> postorder(make_tree())
|
||||
>>> list(postorder(make_tree()))
|
||||
[4, 5, 2, 3, 1]
|
||||
"""
|
||||
return postorder(root.left) + postorder(root.right) + [root.data] if root else []
|
||||
if not root:
|
||||
return
|
||||
yield from postorder(root.left)
|
||||
yield from postorder(root.right)
|
||||
yield root.data
|
||||
|
||||
|
||||
def inorder(root: Node | None) -> list[int]:
|
||||
def inorder(root: Node | None) -> Generator[int, None, None]:
|
||||
"""
|
||||
In-order traversal visits left subtree, root node, right subtree.
|
||||
>>> inorder(make_tree())
|
||||
>>> list(inorder(make_tree()))
|
||||
[4, 2, 5, 1, 3]
|
||||
"""
|
||||
return [*inorder(root.left), root.data, *inorder(root.right)] if root else []
|
||||
if not root:
|
||||
return
|
||||
yield from inorder(root.left)
|
||||
yield root.data
|
||||
yield from inorder(root.right)
|
||||
|
||||
|
||||
def reverse_inorder(root: Node | None) -> list[int]:
|
||||
def reverse_inorder(root: Node | None) -> Generator[int, None, None]:
|
||||
"""
|
||||
Reverse in-order traversal visits right subtree, root node, left subtree.
|
||||
>>> reverse_inorder(make_tree())
|
||||
>>> list(reverse_inorder(make_tree()))
|
||||
[3, 1, 5, 2, 4]
|
||||
"""
|
||||
return (
|
||||
[*reverse_inorder(root.right), root.data, *reverse_inorder(root.left)]
|
||||
if root
|
||||
else []
|
||||
)
|
||||
if not root:
|
||||
return
|
||||
yield from reverse_inorder(root.right)
|
||||
yield root.data
|
||||
yield from reverse_inorder(root.left)
|
||||
|
||||
|
||||
def height(root: Node | None) -> int:
|
||||
|
@ -82,119 +93,109 @@ def height(root: Node | None) -> int:
|
|||
return (max(height(root.left), height(root.right)) + 1) if root else 0
|
||||
|
||||
|
||||
def level_order(root: Node | None) -> Sequence[Node | None]:
|
||||
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.
|
||||
"""
|
||||
output: list[Any] = []
|
||||
|
||||
if root is None:
|
||||
return output
|
||||
return
|
||||
|
||||
process_queue = deque([root])
|
||||
|
||||
while process_queue:
|
||||
node = process_queue.popleft()
|
||||
output.append(node.data)
|
||||
yield node.data
|
||||
|
||||
if node.left:
|
||||
process_queue.append(node.left)
|
||||
if node.right:
|
||||
process_queue.append(node.right)
|
||||
return output
|
||||
|
||||
|
||||
def get_nodes_from_left_to_right(
|
||||
root: Node | None, level: int
|
||||
) -> Sequence[Node | None]:
|
||||
) -> Generator[int, None, None]:
|
||||
"""
|
||||
Returns a list of nodes value from a particular level:
|
||||
Left to right direction of the binary tree.
|
||||
"""
|
||||
output: list[Any] = []
|
||||
|
||||
def populate_output(root: Node | None, level: int) -> None:
|
||||
def populate_output(root: Node | None, level: int) -> Generator[int, None, None]:
|
||||
if not root:
|
||||
return
|
||||
if level == 1:
|
||||
output.append(root.data)
|
||||
yield root.data
|
||||
elif level > 1:
|
||||
populate_output(root.left, level - 1)
|
||||
populate_output(root.right, level - 1)
|
||||
yield from populate_output(root.left, level - 1)
|
||||
yield from populate_output(root.right, level - 1)
|
||||
|
||||
populate_output(root, level)
|
||||
return output
|
||||
yield from populate_output(root, level)
|
||||
|
||||
|
||||
def get_nodes_from_right_to_left(
|
||||
root: Node | None, level: int
|
||||
) -> Sequence[Node | None]:
|
||||
) -> Generator[int, None, None]:
|
||||
"""
|
||||
Returns a list of nodes value from a particular level:
|
||||
Right to left direction of the binary tree.
|
||||
"""
|
||||
output: list[Any] = []
|
||||
|
||||
def populate_output(root: Node | None, level: int) -> None:
|
||||
def populate_output(root: Node | None, level: int) -> Generator[int, None, None]:
|
||||
if root is None:
|
||||
return
|
||||
if level == 1:
|
||||
output.append(root.data)
|
||||
yield root.data
|
||||
elif level > 1:
|
||||
populate_output(root.right, level - 1)
|
||||
populate_output(root.left, level - 1)
|
||||
yield from populate_output(root.right, level - 1)
|
||||
yield from populate_output(root.left, level - 1)
|
||||
|
||||
populate_output(root, level)
|
||||
return output
|
||||
yield from populate_output(root, level)
|
||||
|
||||
|
||||
def zigzag(root: Node | None) -> Sequence[Node | None] | list[Any]:
|
||||
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.
|
||||
"""
|
||||
if root is None:
|
||||
return []
|
||||
|
||||
output: list[Sequence[Node | None]] = []
|
||||
return
|
||||
|
||||
flag = 0
|
||||
height_tree = height(root)
|
||||
|
||||
for h in range(1, height_tree + 1):
|
||||
if not flag:
|
||||
output.append(get_nodes_from_left_to_right(root, h))
|
||||
yield from get_nodes_from_left_to_right(root, h)
|
||||
flag = 1
|
||||
else:
|
||||
output.append(get_nodes_from_right_to_left(root, h))
|
||||
yield from get_nodes_from_right_to_left(root, h)
|
||||
flag = 0
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def main() -> None: # Main function for testing.
|
||||
# Create binary tree.
|
||||
root = make_tree()
|
||||
|
||||
# All Traversals of the binary are as follows:
|
||||
print(f"In-order Traversal: {inorder(root)}")
|
||||
print(f"Reverse In-order Traversal: {reverse_inorder(root)}")
|
||||
print(f"Pre-order Traversal: {preorder(root)}")
|
||||
print(f"Post-order Traversal: {postorder(root)}", "\n")
|
||||
print(f"In-order Traversal: {list(inorder(root))}")
|
||||
print(f"Reverse In-order Traversal: {list(reverse_inorder(root))}")
|
||||
print(f"Pre-order Traversal: {list(preorder(root))}")
|
||||
print(f"Post-order Traversal: {list(postorder(root))}", "\n")
|
||||
|
||||
print(f"Height of Tree: {height(root)}", "\n")
|
||||
|
||||
print("Complete Level Order Traversal: ")
|
||||
print(level_order(root), "\n")
|
||||
print(f"{list(level_order(root))} \n")
|
||||
|
||||
print("Level-wise order Traversal: ")
|
||||
|
||||
for level in range(1, height(root) + 1):
|
||||
print(f"Level {level}:", get_nodes_from_left_to_right(root, level=level))
|
||||
print(f"Level {level}:", list(get_nodes_from_left_to_right(root, level=level)))
|
||||
|
||||
print("\nZigZag order Traversal: ")
|
||||
print(zigzag(root))
|
||||
print(f"{list(zigzag(root))}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
118
data_structures/linked_list/reverse_k_group.py
Normal file
118
data_structures/linked_list/reverse_k_group.py
Normal file
|
@ -0,0 +1,118 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterable, Iterator
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Node:
|
||||
data: int
|
||||
next_node: Node | None = None
|
||||
|
||||
|
||||
class LinkedList:
|
||||
def __init__(self, ints: Iterable[int]) -> None:
|
||||
self.head: Node | None = None
|
||||
for i in ints:
|
||||
self.append(i)
|
||||
|
||||
def __iter__(self) -> Iterator[int]:
|
||||
"""
|
||||
>>> ints = []
|
||||
>>> list(LinkedList(ints)) == ints
|
||||
True
|
||||
>>> ints = tuple(range(5))
|
||||
>>> tuple(LinkedList(ints)) == ints
|
||||
True
|
||||
"""
|
||||
node = self.head
|
||||
while node:
|
||||
yield node.data
|
||||
node = node.next_node
|
||||
|
||||
def __len__(self) -> int:
|
||||
"""
|
||||
>>> for i in range(3):
|
||||
... len(LinkedList(range(i))) == i
|
||||
True
|
||||
True
|
||||
True
|
||||
>>> len(LinkedList("abcdefgh"))
|
||||
8
|
||||
"""
|
||||
return sum(1 for _ in self)
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""
|
||||
>>> str(LinkedList([]))
|
||||
''
|
||||
>>> str(LinkedList(range(5)))
|
||||
'0 -> 1 -> 2 -> 3 -> 4'
|
||||
"""
|
||||
return " -> ".join([str(node) for node in self])
|
||||
|
||||
def append(self, data: int) -> None:
|
||||
"""
|
||||
>>> ll = LinkedList([1, 2])
|
||||
>>> tuple(ll)
|
||||
(1, 2)
|
||||
>>> ll.append(3)
|
||||
>>> tuple(ll)
|
||||
(1, 2, 3)
|
||||
>>> ll.append(4)
|
||||
>>> tuple(ll)
|
||||
(1, 2, 3, 4)
|
||||
>>> len(ll)
|
||||
4
|
||||
"""
|
||||
if not self.head:
|
||||
self.head = Node(data)
|
||||
return
|
||||
node = self.head
|
||||
while node.next_node:
|
||||
node = node.next_node
|
||||
node.next_node = Node(data)
|
||||
|
||||
def reverse_k_nodes(self, group_size: int) -> None:
|
||||
"""
|
||||
reverse nodes within groups of size k
|
||||
>>> ll = LinkedList([1, 2, 3, 4, 5])
|
||||
>>> ll.reverse_k_nodes(2)
|
||||
>>> tuple(ll)
|
||||
(2, 1, 4, 3, 5)
|
||||
>>> str(ll)
|
||||
'2 -> 1 -> 4 -> 3 -> 5'
|
||||
"""
|
||||
if self.head is None or self.head.next_node is None:
|
||||
return
|
||||
|
||||
length = len(self)
|
||||
dummy_head = Node(0)
|
||||
dummy_head.next_node = self.head
|
||||
previous_node = dummy_head
|
||||
|
||||
while length >= group_size:
|
||||
current_node = previous_node.next_node
|
||||
assert current_node
|
||||
next_node = current_node.next_node
|
||||
for _ in range(1, group_size):
|
||||
assert next_node, current_node
|
||||
current_node.next_node = next_node.next_node
|
||||
assert previous_node
|
||||
next_node.next_node = previous_node.next_node
|
||||
previous_node.next_node = next_node
|
||||
next_node = current_node.next_node
|
||||
previous_node = current_node
|
||||
length -= group_size
|
||||
self.head = dummy_head.next_node
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
ll = LinkedList([1, 2, 3, 4, 5])
|
||||
print(f"Original Linked List: {ll}")
|
||||
k = 2
|
||||
ll.reverse_k_nodes(k)
|
||||
print(f"After reversing groups of size {k}: {ll}")
|
156
data_structures/linked_list/rotate_to_the_right.py
Normal file
156
data_structures/linked_list/rotate_to_the_right.py
Normal file
|
@ -0,0 +1,156 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class Node:
|
||||
data: int
|
||||
next_node: Node | None = None
|
||||
|
||||
|
||||
def print_linked_list(head: Node | None) -> None:
|
||||
"""
|
||||
Print the entire linked list iteratively.
|
||||
|
||||
This function prints the elements of a linked list separated by '->'.
|
||||
|
||||
Parameters:
|
||||
head (Node | None): The head of the linked list to be printed,
|
||||
or None if the linked list is empty.
|
||||
|
||||
>>> head = insert_node(None, 0)
|
||||
>>> head = insert_node(head, 2)
|
||||
>>> head = insert_node(head, 1)
|
||||
>>> print_linked_list(head)
|
||||
0->2->1
|
||||
>>> head = insert_node(head, 4)
|
||||
>>> head = insert_node(head, 5)
|
||||
>>> print_linked_list(head)
|
||||
0->2->1->4->5
|
||||
"""
|
||||
if head is None:
|
||||
return
|
||||
while head.next_node is not None:
|
||||
print(head.data, end="->")
|
||||
head = head.next_node
|
||||
print(head.data)
|
||||
|
||||
|
||||
def insert_node(head: Node | None, data: int) -> Node:
|
||||
"""
|
||||
Insert a new node at the end of a linked list and return the new head.
|
||||
|
||||
Parameters:
|
||||
head (Node | None): The head of the linked list.
|
||||
data (int): The data to be inserted into the new node.
|
||||
|
||||
Returns:
|
||||
Node: The new head of the linked list.
|
||||
|
||||
>>> head = insert_node(None, 10)
|
||||
>>> head = insert_node(head, 9)
|
||||
>>> head = insert_node(head, 8)
|
||||
>>> print_linked_list(head)
|
||||
10->9->8
|
||||
"""
|
||||
new_node = Node(data)
|
||||
# If the linked list is empty, the new_node becomes the head
|
||||
if head is None:
|
||||
return new_node
|
||||
|
||||
temp_node = head
|
||||
while temp_node.next_node:
|
||||
temp_node = temp_node.next_node
|
||||
|
||||
temp_node.next_node = new_node # type: ignore
|
||||
return head
|
||||
|
||||
|
||||
def rotate_to_the_right(head: Node, places: int) -> Node:
|
||||
"""
|
||||
Rotate a linked list to the right by places times.
|
||||
|
||||
Parameters:
|
||||
head: The head of the linked list.
|
||||
places: The number of places to rotate.
|
||||
|
||||
Returns:
|
||||
Node: The head of the rotated linked list.
|
||||
|
||||
>>> rotate_to_the_right(None, places=1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: The linked list is empty.
|
||||
>>> head = insert_node(None, 1)
|
||||
>>> rotate_to_the_right(head, places=1) == head
|
||||
True
|
||||
>>> head = insert_node(None, 1)
|
||||
>>> head = insert_node(head, 2)
|
||||
>>> head = insert_node(head, 3)
|
||||
>>> head = insert_node(head, 4)
|
||||
>>> head = insert_node(head, 5)
|
||||
>>> new_head = rotate_to_the_right(head, places=2)
|
||||
>>> print_linked_list(new_head)
|
||||
4->5->1->2->3
|
||||
"""
|
||||
# Check if the list is empty or has only one element
|
||||
if not head:
|
||||
raise ValueError("The linked list is empty.")
|
||||
|
||||
if head.next_node is None:
|
||||
return head
|
||||
|
||||
# Calculate the length of the linked list
|
||||
length = 1
|
||||
temp_node = head
|
||||
while temp_node.next_node is not None:
|
||||
length += 1
|
||||
temp_node = temp_node.next_node
|
||||
|
||||
# Adjust the value of places to avoid places longer than the list.
|
||||
places %= length
|
||||
|
||||
if places == 0:
|
||||
return head # As no rotation is needed.
|
||||
|
||||
# Find the new head position after rotation.
|
||||
new_head_index = length - places
|
||||
|
||||
# Traverse to the new head position
|
||||
temp_node = head
|
||||
for _ in range(new_head_index - 1):
|
||||
assert temp_node.next_node
|
||||
temp_node = temp_node.next_node
|
||||
|
||||
# Update pointers to perform rotation
|
||||
assert temp_node.next_node
|
||||
new_head = temp_node.next_node
|
||||
temp_node.next_node = None
|
||||
temp_node = new_head
|
||||
while temp_node.next_node:
|
||||
temp_node = temp_node.next_node
|
||||
temp_node.next_node = head
|
||||
|
||||
assert new_head
|
||||
return new_head
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
head = insert_node(None, 5)
|
||||
head = insert_node(head, 1)
|
||||
head = insert_node(head, 2)
|
||||
head = insert_node(head, 4)
|
||||
head = insert_node(head, 3)
|
||||
|
||||
print("Original list: ", end="")
|
||||
print_linked_list(head)
|
||||
|
||||
places = 3
|
||||
new_head = rotate_to_the_right(head, places)
|
||||
|
||||
print(f"After {places} iterations: ", end="")
|
||||
print_linked_list(new_head)
|
193
dynamic_programming/smith_waterman.py
Normal file
193
dynamic_programming/smith_waterman.py
Normal file
|
@ -0,0 +1,193 @@
|
|||
"""
|
||||
https://en.wikipedia.org/wiki/Smith%E2%80%93Waterman_algorithm
|
||||
The Smith-Waterman algorithm is a dynamic programming algorithm used for sequence
|
||||
alignment. It is particularly useful for finding similarities between two sequences,
|
||||
such as DNA or protein sequences. In this implementation, gaps are penalized
|
||||
linearly, meaning that the score is reduced by a fixed amount for each gap introduced
|
||||
in the alignment. However, it's important to note that the Smith-Waterman algorithm
|
||||
supports other gap penalty methods as well.
|
||||
"""
|
||||
|
||||
|
||||
def score_function(
|
||||
source_char: str,
|
||||
target_char: str,
|
||||
match: int = 1,
|
||||
mismatch: int = -1,
|
||||
gap: int = -2,
|
||||
) -> int:
|
||||
"""
|
||||
Calculate the score for a character pair based on whether they match or mismatch.
|
||||
Returns 1 if the characters match, -1 if they mismatch, and -2 if either of the
|
||||
characters is a gap.
|
||||
>>> score_function('A', 'A')
|
||||
1
|
||||
>>> score_function('A', 'C')
|
||||
-1
|
||||
>>> score_function('-', 'A')
|
||||
-2
|
||||
>>> score_function('A', '-')
|
||||
-2
|
||||
>>> score_function('-', '-')
|
||||
-2
|
||||
"""
|
||||
if "-" in (source_char, target_char):
|
||||
return gap
|
||||
return match if source_char == target_char else mismatch
|
||||
|
||||
|
||||
def smith_waterman(
|
||||
query: str,
|
||||
subject: str,
|
||||
match: int = 1,
|
||||
mismatch: int = -1,
|
||||
gap: int = -2,
|
||||
) -> list[list[int]]:
|
||||
"""
|
||||
Perform the Smith-Waterman local sequence alignment algorithm.
|
||||
Returns a 2D list representing the score matrix. Each value in the matrix
|
||||
corresponds to the score of the best local alignment ending at that point.
|
||||
>>> smith_waterman('ACAC', 'CA')
|
||||
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]]
|
||||
>>> smith_waterman('acac', 'ca')
|
||||
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]]
|
||||
>>> smith_waterman('ACAC', 'ca')
|
||||
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]]
|
||||
>>> smith_waterman('acac', 'CA')
|
||||
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]]
|
||||
>>> smith_waterman('ACAC', '')
|
||||
[[0], [0], [0], [0], [0]]
|
||||
>>> smith_waterman('', 'CA')
|
||||
[[0, 0, 0]]
|
||||
>>> smith_waterman('ACAC', 'CA')
|
||||
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]]
|
||||
|
||||
>>> smith_waterman('acac', 'ca')
|
||||
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]]
|
||||
|
||||
>>> smith_waterman('ACAC', 'ca')
|
||||
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]]
|
||||
|
||||
>>> smith_waterman('acac', 'CA')
|
||||
[[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]]
|
||||
|
||||
>>> smith_waterman('ACAC', '')
|
||||
[[0], [0], [0], [0], [0]]
|
||||
|
||||
>>> smith_waterman('', 'CA')
|
||||
[[0, 0, 0]]
|
||||
|
||||
>>> smith_waterman('AGT', 'AGT')
|
||||
[[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 2, 0], [0, 0, 0, 3]]
|
||||
|
||||
>>> smith_waterman('AGT', 'GTA')
|
||||
[[0, 0, 0, 0], [0, 0, 0, 1], [0, 1, 0, 0], [0, 0, 2, 0]]
|
||||
|
||||
>>> smith_waterman('AGT', 'GTC')
|
||||
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 2, 0]]
|
||||
|
||||
>>> smith_waterman('AGT', 'G')
|
||||
[[0, 0], [0, 0], [0, 1], [0, 0]]
|
||||
|
||||
>>> smith_waterman('G', 'AGT')
|
||||
[[0, 0, 0, 0], [0, 0, 1, 0]]
|
||||
|
||||
>>> smith_waterman('AGT', 'AGTCT')
|
||||
[[0, 0, 0, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 2, 0, 0, 0], [0, 0, 0, 3, 1, 1]]
|
||||
|
||||
>>> smith_waterman('AGTCT', 'AGT')
|
||||
[[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 2, 0], [0, 0, 0, 3], [0, 0, 0, 1], [0, 0, 0, 1]]
|
||||
|
||||
>>> smith_waterman('AGTCT', 'GTC')
|
||||
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 2, 0], [0, 0, 0, 3], [0, 0, 1, 1]]
|
||||
"""
|
||||
# make both query and subject uppercase
|
||||
query = query.upper()
|
||||
subject = subject.upper()
|
||||
|
||||
# Initialize score matrix
|
||||
m = len(query)
|
||||
n = len(subject)
|
||||
score = [[0] * (n + 1) for _ in range(m + 1)]
|
||||
kwargs = {"match": match, "mismatch": mismatch, "gap": gap}
|
||||
|
||||
for i in range(1, m + 1):
|
||||
for j in range(1, n + 1):
|
||||
# Calculate scores for each cell
|
||||
match = score[i - 1][j - 1] + score_function(
|
||||
query[i - 1], subject[j - 1], **kwargs
|
||||
)
|
||||
delete = score[i - 1][j] + gap
|
||||
insert = score[i][j - 1] + gap
|
||||
|
||||
# Take maximum score
|
||||
score[i][j] = max(0, match, delete, insert)
|
||||
|
||||
return score
|
||||
|
||||
|
||||
def traceback(score: list[list[int]], query: str, subject: str) -> str:
|
||||
r"""
|
||||
Perform traceback to find the optimal local alignment.
|
||||
Starts from the highest scoring cell in the matrix and traces back recursively
|
||||
until a 0 score is found. Returns the alignment strings.
|
||||
>>> traceback([[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]], 'ACAC', 'CA')
|
||||
'CA\nCA'
|
||||
>>> traceback([[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]], 'acac', 'ca')
|
||||
'CA\nCA'
|
||||
>>> traceback([[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]], 'ACAC', 'ca')
|
||||
'CA\nCA'
|
||||
>>> traceback([[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 0, 2], [0, 1, 0]], 'acac', 'CA')
|
||||
'CA\nCA'
|
||||
>>> traceback([[0, 0, 0]], 'ACAC', '')
|
||||
''
|
||||
"""
|
||||
# make both query and subject uppercase
|
||||
query = query.upper()
|
||||
subject = subject.upper()
|
||||
# find the indices of the maximum value in the score matrix
|
||||
max_value = float("-inf")
|
||||
i_max = j_max = 0
|
||||
for i, row in enumerate(score):
|
||||
for j, value in enumerate(row):
|
||||
if value > max_value:
|
||||
max_value = value
|
||||
i_max, j_max = i, j
|
||||
# Traceback logic to find optimal alignment
|
||||
i = i_max
|
||||
j = j_max
|
||||
align1 = ""
|
||||
align2 = ""
|
||||
gap = score_function("-", "-")
|
||||
# guard against empty query or subject
|
||||
if i == 0 or j == 0:
|
||||
return ""
|
||||
while i > 0 and j > 0:
|
||||
if score[i][j] == score[i - 1][j - 1] + score_function(
|
||||
query[i - 1], subject[j - 1]
|
||||
):
|
||||
# optimal path is a diagonal take both letters
|
||||
align1 = query[i - 1] + align1
|
||||
align2 = subject[j - 1] + align2
|
||||
i -= 1
|
||||
j -= 1
|
||||
elif score[i][j] == score[i - 1][j] + gap:
|
||||
# optimal path is a vertical
|
||||
align1 = query[i - 1] + align1
|
||||
align2 = f"-{align2}"
|
||||
i -= 1
|
||||
else:
|
||||
# optimal path is a horizontal
|
||||
align1 = f"-{align1}"
|
||||
align2 = subject[j - 1] + align2
|
||||
j -= 1
|
||||
|
||||
return f"{align1}\n{align2}"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
query = "HEAGAWGHEE"
|
||||
subject = "PAWHEAE"
|
||||
|
||||
score = smith_waterman(query, subject, match=1, mismatch=-1, gap=-2)
|
||||
print(traceback(score, query, subject))
|
|
@ -122,7 +122,7 @@ def local_weight_regression(
|
|||
"""
|
||||
y_pred = np.zeros(len(x_train)) # Initialize array of predictions
|
||||
for i, item in enumerate(x_train):
|
||||
y_pred[i] = item @ local_weight(item, x_train, y_train, tau)
|
||||
y_pred[i] = np.dot(item, local_weight(item, x_train, y_train, tau)).item()
|
||||
|
||||
return y_pred
|
||||
|
||||
|
|
|
@ -75,9 +75,13 @@ class MultinomialNBClassifier:
|
|||
prior_class_i = data_class_i.shape[0] / n_examples
|
||||
self.priors[i] = prior_class_i
|
||||
tot_features_count = data_class_i.sum() # count of all features in class_i
|
||||
features_count = np.array(data_class_i.sum(axis=0))[0] # count of each feature x_j in class_i
|
||||
features_count = np.array(data_class_i.sum(axis=0))[
|
||||
0
|
||||
] # count of each feature x_j in class_i
|
||||
for j, n_j in enumerate(features_count):
|
||||
self.features_probs[i][j] = (self.alpha + n_j) / (tot_features_count + self.alpha * n_features)
|
||||
self.features_probs[i][j] = (self.alpha + n_j) / (
|
||||
tot_features_count + self.alpha * n_features
|
||||
)
|
||||
|
||||
def predict(self, data: sparse.csr_matrix) -> np.array:
|
||||
"""
|
||||
|
@ -109,7 +113,10 @@ class MultinomialNBClassifier:
|
|||
log_priors = np.log(self.priors)
|
||||
for instance in data:
|
||||
theta = instance.multiply(log_features_probs).sum(axis=1)
|
||||
likelihood = [log_prior_class_i + theta[i] for i, log_prior_class_i in enumerate(log_priors)]
|
||||
likelihood = [
|
||||
log_prior_class_i + theta[i]
|
||||
for i, log_prior_class_i in enumerate(log_priors)
|
||||
]
|
||||
y_pred.append(self.classes[np.argmax(likelihood)])
|
||||
return np.array(y_pred)
|
||||
|
||||
|
@ -118,13 +125,13 @@ def main() -> None:
|
|||
"""
|
||||
Performs the text classification on the twenty_newsgroup dataset from sklearn
|
||||
"""
|
||||
newsgroups_train = fetch_20newsgroups(subset='train')
|
||||
newsgroups_test = fetch_20newsgroups(subset='test')
|
||||
x_train = newsgroups_train['data']
|
||||
y_train = newsgroups_train['target']
|
||||
x_test = newsgroups_test['data']
|
||||
y_test = newsgroups_test['target']
|
||||
vectorizer = TfidfVectorizer(stop_words='english')
|
||||
newsgroups_train = fetch_20newsgroups(subset="train")
|
||||
newsgroups_test = fetch_20newsgroups(subset="test")
|
||||
x_train = newsgroups_train["data"]
|
||||
y_train = newsgroups_train["target"]
|
||||
x_test = newsgroups_test["data"]
|
||||
y_test = newsgroups_test["target"]
|
||||
vectorizer = TfidfVectorizer(stop_words="english")
|
||||
x_train = vectorizer.fit_transform(x_train)
|
||||
x_test = vectorizer.transform(x_test)
|
||||
|
||||
|
@ -133,10 +140,12 @@ def main() -> None:
|
|||
model.fit(x_train, y_train)
|
||||
|
||||
y_pred = model.predict(x_test)
|
||||
print("Accuracy of naive bayes text classifier: " + str(accuracy_score(y_test, y_pred)))
|
||||
print(
|
||||
"Accuracy of naive bayes text classifier: "
|
||||
+ str(accuracy_score(y_test, y_pred))
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
doctest.testmod()
|
||||
|
||||
|
|
19
maths/add.py
19
maths/add.py
|
@ -1,19 +0,0 @@
|
|||
"""
|
||||
Just to check
|
||||
"""
|
||||
|
||||
|
||||
def add(a: float, b: float) -> float:
|
||||
"""
|
||||
>>> add(2, 2)
|
||||
4
|
||||
>>> add(2, -2)
|
||||
0
|
||||
"""
|
||||
return a + b
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
a = 5
|
||||
b = 6
|
||||
print(f"The sum of {a} + {b} is {add(a, b)}")
|
|
@ -1,4 +1,4 @@
|
|||
def bin_exp_mod(a, n, b):
|
||||
def bin_exp_mod(a: int, n: int, b: int) -> int:
|
||||
"""
|
||||
>>> bin_exp_mod(3, 4, 5)
|
||||
1
|
||||
|
@ -13,7 +13,7 @@ def bin_exp_mod(a, n, b):
|
|||
if n % 2 == 1:
|
||||
return (bin_exp_mod(a, n - 1, b) * a) % b
|
||||
|
||||
r = bin_exp_mod(a, n / 2, b)
|
||||
r = bin_exp_mod(a, n // 2, b)
|
||||
return (r * r) % b
|
||||
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# Time Complexity : O(logn)
|
||||
|
||||
|
||||
def binary_exponentiation(a, n):
|
||||
def binary_exponentiation(a: int, n: int) -> int:
|
||||
if n == 0:
|
||||
return 1
|
||||
|
||||
|
@ -12,7 +12,7 @@ def binary_exponentiation(a, n):
|
|||
return binary_exponentiation(a, n - 1) * a
|
||||
|
||||
else:
|
||||
b = binary_exponentiation(a, n / 2)
|
||||
b = binary_exponentiation(a, n // 2)
|
||||
return b * b
|
||||
|
||||
|
||||
|
|
|
@ -1,50 +0,0 @@
|
|||
"""
|
||||
* Binary Exponentiation with Multiplication
|
||||
* This is a method to find a*b in a time complexity of O(log b)
|
||||
* This is one of the most commonly used methods of finding result of multiplication.
|
||||
* Also useful in cases where solution to (a*b)%c is required,
|
||||
* where a,b,c can be numbers over the computers calculation limits.
|
||||
* Done using iteration, can also be done using recursion
|
||||
|
||||
* @author chinmoy159
|
||||
* @version 1.0 dated 10/08/2017
|
||||
"""
|
||||
|
||||
|
||||
def b_expo(a, b):
|
||||
res = 0
|
||||
while b > 0:
|
||||
if b & 1:
|
||||
res += a
|
||||
|
||||
a += a
|
||||
b >>= 1
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def b_expo_mod(a, b, c):
|
||||
res = 0
|
||||
while b > 0:
|
||||
if b & 1:
|
||||
res = ((res % c) + (a % c)) % c
|
||||
|
||||
a += a
|
||||
b >>= 1
|
||||
|
||||
return res
|
||||
|
||||
|
||||
"""
|
||||
* Wondering how this method works !
|
||||
* It's pretty simple.
|
||||
* Let's say you need to calculate a ^ b
|
||||
* RULE 1 : a * b = (a+a) * (b/2) ---- example : 4 * 4 = (4+4) * (4/2) = 8 * 2
|
||||
* RULE 2 : IF b is ODD, then ---- a * b = a + (a * (b - 1)) :: where (b - 1) is even.
|
||||
* Once b is even, repeat the process to get a * b
|
||||
* Repeat the process till b = 1 OR b = 0, because a*1 = a AND a*0 = 0
|
||||
*
|
||||
* As far as the modulo is concerned,
|
||||
* the fact : (a+b) % c = ((a%c) + (b%c)) % c
|
||||
* Now apply RULE 1 OR 2, whichever is required.
|
||||
"""
|
|
@ -11,7 +11,7 @@
|
|||
"""
|
||||
|
||||
|
||||
def b_expo(a, b):
|
||||
def b_expo(a: int, b: int) -> int:
|
||||
res = 1
|
||||
while b > 0:
|
||||
if b & 1:
|
||||
|
@ -23,7 +23,7 @@ def b_expo(a, b):
|
|||
return res
|
||||
|
||||
|
||||
def b_expo_mod(a, b, c):
|
||||
def b_expo_mod(a: int, b: int, c: int) -> int:
|
||||
res = 1
|
||||
while b > 0:
|
||||
if b & 1:
|
||||
|
|
101
maths/binary_multiplication.py
Normal file
101
maths/binary_multiplication.py
Normal file
|
@ -0,0 +1,101 @@
|
|||
"""
|
||||
Binary Multiplication
|
||||
This is a method to find a*b in a time complexity of O(log b)
|
||||
This is one of the most commonly used methods of finding result of multiplication.
|
||||
Also useful in cases where solution to (a*b)%c is required,
|
||||
where a,b,c can be numbers over the computers calculation limits.
|
||||
Done using iteration, can also be done using recursion
|
||||
|
||||
Let's say you need to calculate a * b
|
||||
RULE 1 : a * b = (a+a) * (b/2) ---- example : 4 * 4 = (4+4) * (4/2) = 8 * 2
|
||||
RULE 2 : IF b is odd, then ---- a * b = a + (a * (b - 1)), where (b - 1) is even.
|
||||
Once b is even, repeat the process to get a * b
|
||||
Repeat the process until b = 1 or b = 0, because a*1 = a and a*0 = 0
|
||||
|
||||
As far as the modulo is concerned,
|
||||
the fact : (a+b) % c = ((a%c) + (b%c)) % c
|
||||
Now apply RULE 1 or 2, whichever is required.
|
||||
|
||||
@author chinmoy159
|
||||
"""
|
||||
|
||||
|
||||
def binary_multiply(a: int, b: int) -> int:
|
||||
"""
|
||||
Multiply 'a' and 'b' using bitwise multiplication.
|
||||
|
||||
Parameters:
|
||||
a (int): The first number.
|
||||
b (int): The second number.
|
||||
|
||||
Returns:
|
||||
int: a * b
|
||||
|
||||
Examples:
|
||||
>>> binary_multiply(2, 3)
|
||||
6
|
||||
>>> binary_multiply(5, 0)
|
||||
0
|
||||
>>> binary_multiply(3, 4)
|
||||
12
|
||||
>>> binary_multiply(10, 5)
|
||||
50
|
||||
>>> binary_multiply(0, 5)
|
||||
0
|
||||
>>> binary_multiply(2, 1)
|
||||
2
|
||||
>>> binary_multiply(1, 10)
|
||||
10
|
||||
"""
|
||||
res = 0
|
||||
while b > 0:
|
||||
if b & 1:
|
||||
res += a
|
||||
|
||||
a += a
|
||||
b >>= 1
|
||||
|
||||
return res
|
||||
|
||||
|
||||
def binary_mod_multiply(a: int, b: int, modulus: int) -> int:
|
||||
"""
|
||||
Calculate (a * b) % c using binary multiplication and modular arithmetic.
|
||||
|
||||
Parameters:
|
||||
a (int): The first number.
|
||||
b (int): The second number.
|
||||
modulus (int): The modulus.
|
||||
|
||||
Returns:
|
||||
int: (a * b) % modulus.
|
||||
|
||||
Examples:
|
||||
>>> binary_mod_multiply(2, 3, 5)
|
||||
1
|
||||
>>> binary_mod_multiply(5, 0, 7)
|
||||
0
|
||||
>>> binary_mod_multiply(3, 4, 6)
|
||||
0
|
||||
>>> binary_mod_multiply(10, 5, 13)
|
||||
11
|
||||
>>> binary_mod_multiply(2, 1, 5)
|
||||
2
|
||||
>>> binary_mod_multiply(1, 10, 3)
|
||||
1
|
||||
"""
|
||||
res = 0
|
||||
while b > 0:
|
||||
if b & 1:
|
||||
res = ((res % modulus) + (a % modulus)) % modulus
|
||||
|
||||
a += a
|
||||
b >>= 1
|
||||
|
||||
return res
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
|
@ -1,4 +1,4 @@
|
|||
def binomial_coefficient(n, r):
|
||||
def binomial_coefficient(n: int, r: int) -> int:
|
||||
"""
|
||||
Find binomial coefficient using pascals triangle.
|
||||
|
||||
|
|
60
maths/double_factorial.py
Normal file
60
maths/double_factorial.py
Normal file
|
@ -0,0 +1,60 @@
|
|||
def double_factorial_recursive(n: int) -> int:
|
||||
"""
|
||||
Compute double factorial using recursive method.
|
||||
Recursion can be costly for large numbers.
|
||||
|
||||
To learn about the theory behind this algorithm:
|
||||
https://en.wikipedia.org/wiki/Double_factorial
|
||||
|
||||
>>> from math import prod
|
||||
>>> all(double_factorial_recursive(i) == prod(range(i, 0, -2)) for i in range(20))
|
||||
True
|
||||
>>> double_factorial_recursive(0.1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: double_factorial_recursive() only accepts integral values
|
||||
>>> double_factorial_recursive(-1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: double_factorial_recursive() not defined for negative values
|
||||
"""
|
||||
if not isinstance(n, int):
|
||||
raise ValueError("double_factorial_recursive() only accepts integral values")
|
||||
if n < 0:
|
||||
raise ValueError("double_factorial_recursive() not defined for negative values")
|
||||
return 1 if n <= 1 else n * double_factorial_recursive(n - 2)
|
||||
|
||||
|
||||
def double_factorial_iterative(num: int) -> int:
|
||||
"""
|
||||
Compute double factorial using iterative method.
|
||||
|
||||
To learn about the theory behind this algorithm:
|
||||
https://en.wikipedia.org/wiki/Double_factorial
|
||||
|
||||
>>> from math import prod
|
||||
>>> all(double_factorial_iterative(i) == prod(range(i, 0, -2)) for i in range(20))
|
||||
True
|
||||
>>> double_factorial_iterative(0.1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: double_factorial_iterative() only accepts integral values
|
||||
>>> double_factorial_iterative(-1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: double_factorial_iterative() not defined for negative values
|
||||
"""
|
||||
if not isinstance(num, int):
|
||||
raise ValueError("double_factorial_iterative() only accepts integral values")
|
||||
if num < 0:
|
||||
raise ValueError("double_factorial_iterative() not defined for negative values")
|
||||
value = 1
|
||||
for i in range(num, 0, -2):
|
||||
value *= i
|
||||
return value
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
|
@ -1,33 +0,0 @@
|
|||
def double_factorial(num: int) -> int:
|
||||
"""
|
||||
Compute double factorial using iterative method.
|
||||
|
||||
To learn about the theory behind this algorithm:
|
||||
https://en.wikipedia.org/wiki/Double_factorial
|
||||
|
||||
>>> import math
|
||||
>>> all(double_factorial(i) == math.prod(range(i, 0, -2)) for i in range(20))
|
||||
True
|
||||
>>> double_factorial(0.1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: double_factorial() only accepts integral values
|
||||
>>> double_factorial(-1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: double_factorial() not defined for negative values
|
||||
"""
|
||||
if not isinstance(num, int):
|
||||
raise ValueError("double_factorial() only accepts integral values")
|
||||
if num < 0:
|
||||
raise ValueError("double_factorial() not defined for negative values")
|
||||
value = 1
|
||||
for i in range(num, 0, -2):
|
||||
value *= i
|
||||
return value
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
|
@ -1,31 +0,0 @@
|
|||
def double_factorial(n: int) -> int:
|
||||
"""
|
||||
Compute double factorial using recursive method.
|
||||
Recursion can be costly for large numbers.
|
||||
|
||||
To learn about the theory behind this algorithm:
|
||||
https://en.wikipedia.org/wiki/Double_factorial
|
||||
|
||||
>>> import math
|
||||
>>> all(double_factorial(i) == math.prod(range(i, 0, -2)) for i in range(20))
|
||||
True
|
||||
>>> double_factorial(0.1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: double_factorial() only accepts integral values
|
||||
>>> double_factorial(-1)
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
ValueError: double_factorial() not defined for negative values
|
||||
"""
|
||||
if not isinstance(n, int):
|
||||
raise ValueError("double_factorial() only accepts integral values")
|
||||
if n < 0:
|
||||
raise ValueError("double_factorial() not defined for negative values")
|
||||
return 1 if n <= 1 else n * double_factorial(n - 2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
|
@ -17,13 +17,13 @@ def maclaurin_sin(theta: float, accuracy: int = 30) -> float:
|
|||
>>> all(isclose(maclaurin_sin(x, 50), sin(x)) for x in range(-25, 25))
|
||||
True
|
||||
>>> maclaurin_sin(10)
|
||||
-0.544021110889369
|
||||
-0.5440211108893691
|
||||
>>> maclaurin_sin(-10)
|
||||
0.5440211108893703
|
||||
0.5440211108893704
|
||||
>>> maclaurin_sin(10, 15)
|
||||
-0.5440211108893689
|
||||
-0.544021110889369
|
||||
>>> maclaurin_sin(-10, 15)
|
||||
0.5440211108893703
|
||||
0.5440211108893704
|
||||
>>> maclaurin_sin("10")
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
|
@ -69,11 +69,11 @@ def maclaurin_cos(theta: float, accuracy: int = 30) -> float:
|
|||
>>> all(isclose(maclaurin_cos(x, 50), cos(x)) for x in range(-25, 25))
|
||||
True
|
||||
>>> maclaurin_cos(5)
|
||||
0.28366218546322675
|
||||
0.2836621854632268
|
||||
>>> maclaurin_cos(-5)
|
||||
0.2836621854632266
|
||||
0.2836621854632265
|
||||
>>> maclaurin_cos(10, 15)
|
||||
-0.8390715290764525
|
||||
-0.8390715290764524
|
||||
>>> maclaurin_cos(-10, 15)
|
||||
-0.8390715290764521
|
||||
>>> maclaurin_cos("10")
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
import random
|
||||
|
||||
from .binary_exp_mod import bin_exp_mod
|
||||
|
||||
|
||||
# This is a probabilistic check to test primality, useful for big numbers!
|
||||
# if it's a prime, it will return true
|
||||
# if it's not a prime, the chance of it returning true is at most 1/4**prec
|
||||
def is_prime_big(n, prec=1000):
|
||||
"""
|
||||
>>> from maths.prime_check import is_prime
|
||||
>>> # all(is_prime_big(i) == is_prime(i) for i in range(1000)) # 3.45s
|
||||
>>> all(is_prime_big(i) == is_prime(i) for i in range(256))
|
||||
True
|
||||
"""
|
||||
if n < 2:
|
||||
return False
|
||||
|
||||
if n % 2 == 0:
|
||||
return n == 2
|
||||
|
||||
# this means n is odd
|
||||
d = n - 1
|
||||
exp = 0
|
||||
while d % 2 == 0:
|
||||
d /= 2
|
||||
exp += 1
|
||||
|
||||
# n - 1=d*(2**exp)
|
||||
count = 0
|
||||
while count < prec:
|
||||
a = random.randint(2, n - 1)
|
||||
b = bin_exp_mod(a, d, n)
|
||||
if b != 1:
|
||||
flag = True
|
||||
for _ in range(exp):
|
||||
if b == n - 1:
|
||||
flag = False
|
||||
break
|
||||
b = b * b
|
||||
b %= n
|
||||
if flag:
|
||||
return False
|
||||
count += 1
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
n = abs(int(input("Enter bound : ").strip()))
|
||||
print("Here's the list of primes:")
|
||||
print(", ".join(str(i) for i in range(n + 1) if is_prime_big(i)))
|
47
maths/three_sum.py
Normal file
47
maths/three_sum.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
"""
|
||||
https://en.wikipedia.org/wiki/3SUM
|
||||
"""
|
||||
|
||||
|
||||
def three_sum(nums: list[int]) -> list[list[int]]:
|
||||
"""
|
||||
Find all unique triplets in a sorted array of integers that sum up to zero.
|
||||
|
||||
Args:
|
||||
nums: A sorted list of integers.
|
||||
|
||||
Returns:
|
||||
A list of lists containing unique triplets that sum up to zero.
|
||||
|
||||
>>> three_sum([-1, 0, 1, 2, -1, -4])
|
||||
[[-1, -1, 2], [-1, 0, 1]]
|
||||
>>> three_sum([1, 2, 3, 4])
|
||||
[]
|
||||
"""
|
||||
nums.sort()
|
||||
ans = []
|
||||
for i in range(len(nums) - 2):
|
||||
if i == 0 or (nums[i] != nums[i - 1]):
|
||||
low, high, c = i + 1, len(nums) - 1, 0 - nums[i]
|
||||
while low < high:
|
||||
if nums[low] + nums[high] == c:
|
||||
ans.append([nums[i], nums[low], nums[high]])
|
||||
|
||||
while low < high and nums[low] == nums[low + 1]:
|
||||
low += 1
|
||||
while low < high and nums[high] == nums[high - 1]:
|
||||
high -= 1
|
||||
|
||||
low += 1
|
||||
high -= 1
|
||||
elif nums[low] + nums[high] < c:
|
||||
low += 1
|
||||
else:
|
||||
high -= 1
|
||||
return ans
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
396
other/word_search.py
Normal file
396
other/word_search.py
Normal file
|
@ -0,0 +1,396 @@
|
|||
"""
|
||||
Creates a random wordsearch with eight different directions
|
||||
that are best described as compass locations.
|
||||
|
||||
@ https://en.wikipedia.org/wiki/Word_search
|
||||
"""
|
||||
|
||||
|
||||
from random import choice, randint, shuffle
|
||||
|
||||
# The words to display on the word search -
|
||||
# can be made dynamic by randonly selecting a certain number of
|
||||
# words from a predefined word file, while ensuring the character
|
||||
# count fits within the matrix size (n x m)
|
||||
WORDS = ["cat", "dog", "snake", "fish"]
|
||||
|
||||
WIDTH = 10
|
||||
HEIGHT = 10
|
||||
|
||||
|
||||
class WordSearch:
|
||||
"""
|
||||
>>> ws = WordSearch(WORDS, WIDTH, HEIGHT)
|
||||
>>> ws.board # doctest: +ELLIPSIS
|
||||
[[None, ..., None], ..., [None, ..., None]]
|
||||
>>> ws.generate_board()
|
||||
"""
|
||||
|
||||
def __init__(self, words: list[str], width: int, height: int) -> None:
|
||||
self.words = words
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
# Board matrix holding each letter
|
||||
self.board: list[list[str | None]] = [[None] * width for _ in range(height)]
|
||||
|
||||
def insert_north(self, word: str, rows: list[int], cols: list[int]) -> None:
|
||||
"""
|
||||
>>> ws = WordSearch(WORDS, 3, 3)
|
||||
>>> ws.insert_north("cat", [2], [2])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[[None, None, 't'],
|
||||
[None, None, 'a'],
|
||||
[None, None, 'c']]
|
||||
>>> ws.insert_north("at", [0, 1, 2], [2, 1])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[[None, 't', 't'],
|
||||
[None, 'a', 'a'],
|
||||
[None, None, 'c']]
|
||||
"""
|
||||
word_length = len(word)
|
||||
# Attempt to insert the word into each row and when successful, exit
|
||||
for row in rows:
|
||||
# Check if there is space above the row to fit in the word
|
||||
if word_length > row + 1:
|
||||
continue
|
||||
|
||||
# Attempt to insert the word into each column
|
||||
for col in cols:
|
||||
# Only check to be made here is if there are existing letters
|
||||
# above the column that will be overwritten
|
||||
letters_above = [self.board[row - i][col] for i in range(word_length)]
|
||||
if all(letter is None for letter in letters_above):
|
||||
# Successful, insert the word north
|
||||
for i in range(word_length):
|
||||
self.board[row - i][col] = word[i]
|
||||
return
|
||||
|
||||
def insert_northeast(self, word: str, rows: list[int], cols: list[int]) -> None:
|
||||
"""
|
||||
>>> ws = WordSearch(WORDS, 3, 3)
|
||||
>>> ws.insert_northeast("cat", [2], [0])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[[None, None, 't'],
|
||||
[None, 'a', None],
|
||||
['c', None, None]]
|
||||
>>> ws.insert_northeast("at", [0, 1], [2, 1, 0])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[[None, 't', 't'],
|
||||
['a', 'a', None],
|
||||
['c', None, None]]
|
||||
"""
|
||||
word_length = len(word)
|
||||
# Attempt to insert the word into each row and when successful, exit
|
||||
for row in rows:
|
||||
# Check if there is space for the word above the row
|
||||
if word_length > row + 1:
|
||||
continue
|
||||
|
||||
# Attempt to insert the word into each column
|
||||
for col in cols:
|
||||
# Check if there is space to the right of the word as well as above
|
||||
if word_length + col > self.width:
|
||||
continue
|
||||
|
||||
# Check if there are existing letters
|
||||
# to the right of the column that will be overwritten
|
||||
letters_diagonal_left = [
|
||||
self.board[row - i][col + i] for i in range(word_length)
|
||||
]
|
||||
if all(letter is None for letter in letters_diagonal_left):
|
||||
# Successful, insert the word northeast
|
||||
for i in range(word_length):
|
||||
self.board[row - i][col + i] = word[i]
|
||||
return
|
||||
|
||||
def insert_east(self, word: str, rows: list[int], cols: list[int]) -> None:
|
||||
"""
|
||||
>>> ws = WordSearch(WORDS, 3, 3)
|
||||
>>> ws.insert_east("cat", [1], [0])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[[None, None, None],
|
||||
['c', 'a', 't'],
|
||||
[None, None, None]]
|
||||
>>> ws.insert_east("at", [1, 0], [2, 1, 0])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[[None, 'a', 't'],
|
||||
['c', 'a', 't'],
|
||||
[None, None, None]]
|
||||
"""
|
||||
word_length = len(word)
|
||||
# Attempt to insert the word into each row and when successful, exit
|
||||
for row in rows:
|
||||
# Attempt to insert the word into each column
|
||||
for col in cols:
|
||||
# Check if there is space to the right of the word
|
||||
if word_length + col > self.width:
|
||||
continue
|
||||
|
||||
# Check if there are existing letters
|
||||
# to the right of the column that will be overwritten
|
||||
letters_left = [self.board[row][col + i] for i in range(word_length)]
|
||||
if all(letter is None for letter in letters_left):
|
||||
# Successful, insert the word east
|
||||
for i in range(word_length):
|
||||
self.board[row][col + i] = word[i]
|
||||
return
|
||||
|
||||
def insert_southeast(self, word: str, rows: list[int], cols: list[int]) -> None:
|
||||
"""
|
||||
>>> ws = WordSearch(WORDS, 3, 3)
|
||||
>>> ws.insert_southeast("cat", [0], [0])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[['c', None, None],
|
||||
[None, 'a', None],
|
||||
[None, None, 't']]
|
||||
>>> ws.insert_southeast("at", [1, 0], [2, 1, 0])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[['c', None, None],
|
||||
['a', 'a', None],
|
||||
[None, 't', 't']]
|
||||
"""
|
||||
word_length = len(word)
|
||||
# Attempt to insert the word into each row and when successful, exit
|
||||
for row in rows:
|
||||
# Check if there is space for the word below the row
|
||||
if word_length + row > self.height:
|
||||
continue
|
||||
|
||||
# Attempt to insert the word into each column
|
||||
for col in cols:
|
||||
# Check if there is space to the right of the word as well as below
|
||||
if word_length + col > self.width:
|
||||
continue
|
||||
|
||||
# Check if there are existing letters
|
||||
# to the right of the column that will be overwritten
|
||||
letters_diagonal_left = [
|
||||
self.board[row + i][col + i] for i in range(word_length)
|
||||
]
|
||||
if all(letter is None for letter in letters_diagonal_left):
|
||||
# Successful, insert the word southeast
|
||||
for i in range(word_length):
|
||||
self.board[row + i][col + i] = word[i]
|
||||
return
|
||||
|
||||
def insert_south(self, word: str, rows: list[int], cols: list[int]) -> None:
|
||||
"""
|
||||
>>> ws = WordSearch(WORDS, 3, 3)
|
||||
>>> ws.insert_south("cat", [0], [0])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[['c', None, None],
|
||||
['a', None, None],
|
||||
['t', None, None]]
|
||||
>>> ws.insert_south("at", [2, 1, 0], [0, 1, 2])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[['c', None, None],
|
||||
['a', 'a', None],
|
||||
['t', 't', None]]
|
||||
"""
|
||||
word_length = len(word)
|
||||
# Attempt to insert the word into each row and when successful, exit
|
||||
for row in rows:
|
||||
# Check if there is space below the row to fit in the word
|
||||
if word_length + row > self.height:
|
||||
continue
|
||||
|
||||
# Attempt to insert the word into each column
|
||||
for col in cols:
|
||||
# Only check to be made here is if there are existing letters
|
||||
# below the column that will be overwritten
|
||||
letters_below = [self.board[row + i][col] for i in range(word_length)]
|
||||
if all(letter is None for letter in letters_below):
|
||||
# Successful, insert the word south
|
||||
for i in range(word_length):
|
||||
self.board[row + i][col] = word[i]
|
||||
return
|
||||
|
||||
def insert_southwest(self, word: str, rows: list[int], cols: list[int]) -> None:
|
||||
"""
|
||||
>>> ws = WordSearch(WORDS, 3, 3)
|
||||
>>> ws.insert_southwest("cat", [0], [2])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[[None, None, 'c'],
|
||||
[None, 'a', None],
|
||||
['t', None, None]]
|
||||
>>> ws.insert_southwest("at", [1, 2], [2, 1, 0])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[[None, None, 'c'],
|
||||
[None, 'a', 'a'],
|
||||
['t', 't', None]]
|
||||
"""
|
||||
word_length = len(word)
|
||||
# Attempt to insert the word into each row and when successful, exit
|
||||
for row in rows:
|
||||
# Check if there is space for the word below the row
|
||||
if word_length + row > self.height:
|
||||
continue
|
||||
|
||||
# Attempt to insert the word into each column
|
||||
for col in cols:
|
||||
# Check if there is space to the left of the word as well as below
|
||||
if word_length > col + 1:
|
||||
continue
|
||||
|
||||
# Check if there are existing letters
|
||||
# to the right of the column that will be overwritten
|
||||
letters_diagonal_left = [
|
||||
self.board[row + i][col - i] for i in range(word_length)
|
||||
]
|
||||
if all(letter is None for letter in letters_diagonal_left):
|
||||
# Successful, insert the word southwest
|
||||
for i in range(word_length):
|
||||
self.board[row + i][col - i] = word[i]
|
||||
return
|
||||
|
||||
def insert_west(self, word: str, rows: list[int], cols: list[int]) -> None:
|
||||
"""
|
||||
>>> ws = WordSearch(WORDS, 3, 3)
|
||||
>>> ws.insert_west("cat", [1], [2])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[[None, None, None],
|
||||
['t', 'a', 'c'],
|
||||
[None, None, None]]
|
||||
>>> ws.insert_west("at", [1, 0], [1, 2, 0])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[['t', 'a', None],
|
||||
['t', 'a', 'c'],
|
||||
[None, None, None]]
|
||||
"""
|
||||
word_length = len(word)
|
||||
# Attempt to insert the word into each row and when successful, exit
|
||||
for row in rows:
|
||||
# Attempt to insert the word into each column
|
||||
for col in cols:
|
||||
# Check if there is space to the left of the word
|
||||
if word_length > col + 1:
|
||||
continue
|
||||
|
||||
# Check if there are existing letters
|
||||
# to the left of the column that will be overwritten
|
||||
letters_left = [self.board[row][col - i] for i in range(word_length)]
|
||||
if all(letter is None for letter in letters_left):
|
||||
# Successful, insert the word west
|
||||
for i in range(word_length):
|
||||
self.board[row][col - i] = word[i]
|
||||
return
|
||||
|
||||
def insert_northwest(self, word: str, rows: list[int], cols: list[int]) -> None:
|
||||
"""
|
||||
>>> ws = WordSearch(WORDS, 3, 3)
|
||||
>>> ws.insert_northwest("cat", [2], [2])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[['t', None, None],
|
||||
[None, 'a', None],
|
||||
[None, None, 'c']]
|
||||
>>> ws.insert_northwest("at", [1, 2], [0, 1])
|
||||
>>> ws.board # doctest: +NORMALIZE_WHITESPACE
|
||||
[['t', None, None],
|
||||
['t', 'a', None],
|
||||
[None, 'a', 'c']]
|
||||
"""
|
||||
word_length = len(word)
|
||||
# Attempt to insert the word into each row and when successful, exit
|
||||
for row in rows:
|
||||
# Check if there is space for the word above the row
|
||||
if word_length > row + 1:
|
||||
continue
|
||||
|
||||
# Attempt to insert the word into each column
|
||||
for col in cols:
|
||||
# Check if there is space to the left of the word as well as above
|
||||
if word_length > col + 1:
|
||||
continue
|
||||
|
||||
# Check if there are existing letters
|
||||
# to the right of the column that will be overwritten
|
||||
letters_diagonal_left = [
|
||||
self.board[row - i][col - i] for i in range(word_length)
|
||||
]
|
||||
if all(letter is None for letter in letters_diagonal_left):
|
||||
# Successful, insert the word northwest
|
||||
for i in range(word_length):
|
||||
self.board[row - i][col - i] = word[i]
|
||||
return
|
||||
|
||||
def generate_board(self) -> None:
|
||||
"""
|
||||
Generates a board with a random direction for each word.
|
||||
|
||||
>>> wt = WordSearch(WORDS, WIDTH, HEIGHT)
|
||||
>>> wt.generate_board()
|
||||
>>> len(list(filter(lambda word: word is not None, sum(wt.board, start=[])))
|
||||
... ) == sum(map(lambda word: len(word), WORDS))
|
||||
True
|
||||
"""
|
||||
directions = (
|
||||
self.insert_north,
|
||||
self.insert_northeast,
|
||||
self.insert_east,
|
||||
self.insert_southeast,
|
||||
self.insert_south,
|
||||
self.insert_southwest,
|
||||
self.insert_west,
|
||||
self.insert_northwest,
|
||||
)
|
||||
for word in self.words:
|
||||
# Shuffle the row order and column order that is used when brute forcing
|
||||
# the insertion of the word
|
||||
rows, cols = list(range(self.height)), list(range(self.width))
|
||||
shuffle(rows)
|
||||
shuffle(cols)
|
||||
|
||||
# Insert the word via the direction
|
||||
choice(directions)(word, rows, cols)
|
||||
|
||||
|
||||
def visualise_word_search(
|
||||
board: list[list[str | None]] | None = None, *, add_fake_chars: bool = True
|
||||
) -> None:
|
||||
"""
|
||||
Graphically displays the word search in the terminal.
|
||||
|
||||
>>> ws = WordSearch(WORDS, 5, 5)
|
||||
>>> ws.insert_north("cat", [4], [4])
|
||||
>>> visualise_word_search(
|
||||
... ws.board, add_fake_chars=False) # doctest: +NORMALIZE_WHITESPACE
|
||||
# # # # #
|
||||
# # # # #
|
||||
# # # # t
|
||||
# # # # a
|
||||
# # # # c
|
||||
>>> ws.insert_northeast("snake", [4], [4, 3, 2, 1, 0])
|
||||
>>> visualise_word_search(
|
||||
... ws.board, add_fake_chars=False) # doctest: +NORMALIZE_WHITESPACE
|
||||
# # # # e
|
||||
# # # k #
|
||||
# # a # t
|
||||
# n # # a
|
||||
s # # # c
|
||||
"""
|
||||
if board is None:
|
||||
word_search = WordSearch(WORDS, WIDTH, HEIGHT)
|
||||
word_search.generate_board()
|
||||
board = word_search.board
|
||||
|
||||
result = ""
|
||||
for row in range(len(board)):
|
||||
for col in range(len(board[0])):
|
||||
character = "#"
|
||||
if (letter := board[row][col]) is not None:
|
||||
character = letter
|
||||
# Empty char, so add a fake char
|
||||
elif add_fake_chars:
|
||||
character = chr(randint(97, 122))
|
||||
result += f"{character} "
|
||||
result += "\n"
|
||||
print(result, end="")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
|
||||
visualise_word_search()
|
|
@ -21,6 +21,8 @@ Sum of phi(d), for all d|n = n. This result can be used to find phi(n) using a s
|
|||
Time: 1 sec
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
def solution(limit: int = 1_000_000) -> int:
|
||||
"""
|
||||
|
@ -33,14 +35,15 @@ def solution(limit: int = 1_000_000) -> int:
|
|||
304191
|
||||
"""
|
||||
|
||||
phi = [i - 1 for i in range(limit + 1)]
|
||||
# generating an array from -1 to limit
|
||||
phi = np.arange(-1, limit)
|
||||
|
||||
for i in range(2, limit + 1):
|
||||
if phi[i] == i - 1:
|
||||
for j in range(2 * i, limit + 1, i):
|
||||
phi[j] -= phi[j] // i
|
||||
ind = np.arange(2 * i, limit + 1, i) # indexes for selection
|
||||
phi[ind] -= phi[ind] // i
|
||||
|
||||
return sum(phi[2 : limit + 1])
|
||||
return np.sum(phi[2 : limit + 1])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
1
quantum/deutsch_jozsa.py → quantum/deutsch_jozsa.py.DISABLED.txt
Executable file → Normal file
1
quantum/deutsch_jozsa.py → quantum/deutsch_jozsa.py.DISABLED.txt
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
|||
# DISABLED!!
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Deutsch-Jozsa Algorithm is one of the first examples of a quantum
|
1
quantum/half_adder.py → quantum/half_adder.py.DISABLED.txt
Executable file → Normal file
1
quantum/half_adder.py → quantum/half_adder.py.DISABLED.txt
Executable file → Normal file
|
@ -1,3 +1,4 @@
|
|||
# DISABLED!!
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Build a half-adder quantum circuit that takes two bits as input,
|
|
@ -9,15 +9,15 @@ opencv-python
|
|||
pandas
|
||||
pillow
|
||||
projectq
|
||||
qiskit
|
||||
qiskit-aer
|
||||
qiskit ; python_version < '3.12'
|
||||
qiskit-aer ; python_version < '3.12'
|
||||
requests
|
||||
rich
|
||||
scikit-fuzzy
|
||||
scikit-learn
|
||||
statsmodels
|
||||
sympy
|
||||
tensorflow
|
||||
tensorflow ; python_version < '3.12'
|
||||
texttable
|
||||
tweepy
|
||||
xgboost
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
from random import randint
|
||||
from tempfile import TemporaryFile
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
def _in_place_quick_sort(a, start, end):
|
||||
count = 0
|
||||
if start < end:
|
||||
pivot = randint(start, end)
|
||||
temp = a[end]
|
||||
a[end] = a[pivot]
|
||||
a[pivot] = temp
|
||||
|
||||
p, count = _in_place_partition(a, start, end)
|
||||
count += _in_place_quick_sort(a, start, p - 1)
|
||||
count += _in_place_quick_sort(a, p + 1, end)
|
||||
return count
|
||||
|
||||
|
||||
def _in_place_partition(a, start, end):
|
||||
count = 0
|
||||
pivot = randint(start, end)
|
||||
temp = a[end]
|
||||
a[end] = a[pivot]
|
||||
a[pivot] = temp
|
||||
new_pivot_index = start - 1
|
||||
for index in range(start, end):
|
||||
count += 1
|
||||
if a[index] < a[end]: # check if current val is less than pivot value
|
||||
new_pivot_index = new_pivot_index + 1
|
||||
temp = a[new_pivot_index]
|
||||
a[new_pivot_index] = a[index]
|
||||
a[index] = temp
|
||||
|
||||
temp = a[new_pivot_index + 1]
|
||||
a[new_pivot_index + 1] = a[end]
|
||||
a[end] = temp
|
||||
return new_pivot_index + 1, count
|
||||
|
||||
|
||||
outfile = TemporaryFile()
|
||||
p = 100 # 1000 elements are to be sorted
|
||||
|
||||
|
||||
mu, sigma = 0, 1 # mean and standard deviation
|
||||
X = np.random.normal(mu, sigma, p)
|
||||
np.save(outfile, X)
|
||||
print("The array is")
|
||||
print(X)
|
||||
|
||||
|
||||
outfile.seek(0) # using the same array
|
||||
M = np.load(outfile)
|
||||
r = len(M) - 1
|
||||
z = _in_place_quick_sort(M, 0, r)
|
||||
|
||||
print(
|
||||
"No of Comparisons for 100 elements selected from a standard normal distribution"
|
||||
"is :"
|
||||
)
|
||||
print(z)
|
|
@ -1,44 +0,0 @@
|
|||
"""
|
||||
Picks the random index as the pivot
|
||||
"""
|
||||
import random
|
||||
|
||||
|
||||
def partition(a, left_index, right_index):
|
||||
pivot = a[left_index]
|
||||
i = left_index + 1
|
||||
for j in range(left_index + 1, right_index):
|
||||
if a[j] < pivot:
|
||||
a[j], a[i] = a[i], a[j]
|
||||
i += 1
|
||||
a[left_index], a[i - 1] = a[i - 1], a[left_index]
|
||||
return i - 1
|
||||
|
||||
|
||||
def quick_sort_random(a, left, right):
|
||||
if left < right:
|
||||
pivot = random.randint(left, right - 1)
|
||||
a[pivot], a[left] = (
|
||||
a[left],
|
||||
a[pivot],
|
||||
) # switches the pivot with the left most bound
|
||||
pivot_index = partition(a, left, right)
|
||||
quick_sort_random(
|
||||
a, left, pivot_index
|
||||
) # recursive quicksort to the left of the pivot point
|
||||
quick_sort_random(
|
||||
a, pivot_index + 1, right
|
||||
) # recursive quicksort to the right of the pivot point
|
||||
|
||||
|
||||
def main():
|
||||
user_input = input("Enter numbers separated by a comma:\n").strip()
|
||||
arr = [int(item) for item in user_input.split(",")]
|
||||
|
||||
quick_sort_random(arr, 0, len(arr))
|
||||
|
||||
print(arr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -33,7 +33,7 @@ def get_subreddit_data(
|
|||
headers={"User-agent": "A random string"},
|
||||
)
|
||||
if response.status_code == 429:
|
||||
raise requests.HTTPError
|
||||
raise requests.HTTPError(response=response)
|
||||
|
||||
data = response.json()
|
||||
if not wanted_data:
|
||||
|
|
Loading…
Reference in New Issue
Block a user