Skip to content

Commit 21e04ab

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents f103a45 + ad9948d commit 21e04ab

19 files changed

+1051
-108
lines changed

Diff for: DIRECTORY.md

+10
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
* [Bitwise Addition Recursive](bit_manipulation/bitwise_addition_recursive.py)
3535
* [Count 1S Brian Kernighan Method](bit_manipulation/count_1s_brian_kernighan_method.py)
3636
* [Count Number Of One Bits](bit_manipulation/count_number_of_one_bits.py)
37+
* [Excess 3 Code](bit_manipulation/excess_3_code.py)
3738
* [Gray Code Sequence](bit_manipulation/gray_code_sequence.py)
3839
* [Highest Set Bit](bit_manipulation/highest_set_bit.py)
3940
* [Index Of Rightmost Set Bit](bit_manipulation/index_of_rightmost_set_bit.py)
@@ -170,7 +171,10 @@
170171
* Arrays
171172
* [Equilibrium Index In Array](data_structures/arrays/equilibrium_index_in_array.py)
172173
* [Find Triplets With 0 Sum](data_structures/arrays/find_triplets_with_0_sum.py)
174+
* [Index 2D Array In 1D](data_structures/arrays/index_2d_array_in_1d.py)
175+
* [Kth Largest Element](data_structures/arrays/kth_largest_element.py)
173176
* [Median Two Array](data_structures/arrays/median_two_array.py)
177+
* [Monotonic Array](data_structures/arrays/monotonic_array.py)
174178
* [Pairs With Given Sum](data_structures/arrays/pairs_with_given_sum.py)
175179
* [Permutations](data_structures/arrays/permutations.py)
176180
* [Prefix Sum](data_structures/arrays/prefix_sum.py)
@@ -368,6 +372,7 @@
368372
## Electronics
369373
* [Apparent Power](electronics/apparent_power.py)
370374
* [Builtin Voltage](electronics/builtin_voltage.py)
375+
* [Capacitor Equivalence](electronics/capacitor_equivalence.py)
371376
* [Carrier Concentration](electronics/carrier_concentration.py)
372377
* [Charging Capacitor](electronics/charging_capacitor.py)
373378
* [Charging Inductor](electronics/charging_inductor.py)
@@ -531,12 +536,14 @@
531536
## Machine Learning
532537
* [Apriori Algorithm](machine_learning/apriori_algorithm.py)
533538
* [Astar](machine_learning/astar.py)
539+
* [Automatic Differentiation](machine_learning/automatic_differentiation.py)
534540
* [Data Transformations](machine_learning/data_transformations.py)
535541
* [Decision Tree](machine_learning/decision_tree.py)
536542
* [Dimensionality Reduction](machine_learning/dimensionality_reduction.py)
537543
* Forecasting
538544
* [Run](machine_learning/forecasting/run.py)
539545
* [Frequent Pattern Growth](machine_learning/frequent_pattern_growth.py)
546+
* [Gradient Boosting Classifier](machine_learning/gradient_boosting_classifier.py)
540547
* [Gradient Descent](machine_learning/gradient_descent.py)
541548
* [K Means Clust](machine_learning/k_means_clust.py)
542549
* [K Nearest Neighbours](machine_learning/k_nearest_neighbours.py)
@@ -598,6 +605,7 @@
598605
* [Extended Euclidean Algorithm](maths/extended_euclidean_algorithm.py)
599606
* [Factorial](maths/factorial.py)
600607
* [Factors](maths/factors.py)
608+
* [Fast Inverse Sqrt](maths/fast_inverse_sqrt.py)
601609
* [Fermat Little Theorem](maths/fermat_little_theorem.py)
602610
* [Fibonacci](maths/fibonacci.py)
603611
* [Find Max](maths/find_max.py)
@@ -648,6 +656,7 @@
648656
* [Numerical Integration](maths/numerical_analysis/numerical_integration.py)
649657
* [Runge Kutta](maths/numerical_analysis/runge_kutta.py)
650658
* [Runge Kutta Fehlberg 45](maths/numerical_analysis/runge_kutta_fehlberg_45.py)
659+
* [Runge Kutta Gills](maths/numerical_analysis/runge_kutta_gills.py)
651660
* [Secant Method](maths/numerical_analysis/secant_method.py)
652661
* [Simpson Rule](maths/numerical_analysis/simpson_rule.py)
653662
* [Square Root](maths/numerical_analysis/square_root.py)
@@ -814,6 +823,7 @@
814823
* [Ideal Gas Law](physics/ideal_gas_law.py)
815824
* [In Static Equilibrium](physics/in_static_equilibrium.py)
816825
* [Kinetic Energy](physics/kinetic_energy.py)
826+
* [Lens Formulae](physics/lens_formulae.py)
817827
* [Lorentz Transformation Four Vector](physics/lorentz_transformation_four_vector.py)
818828
* [Malus Law](physics/malus_law.py)
819829
* [Mass Energy Equivalence](physics/mass_energy_equivalence.py)

Diff for: backtracking/generate_parentheses.py

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
"""
2+
author: Aayush Soni
3+
Given n pairs of parentheses, write a function to generate all
4+
combinations of well-formed parentheses.
5+
Input: n = 2
6+
Output: ["(())","()()"]
7+
Leetcode link: https://leetcode.com/problems/generate-parentheses/description/
8+
"""
9+
10+
11+
def backtrack(
12+
partial: str, open_count: int, close_count: int, n: int, result: list[str]
13+
) -> None:
14+
"""
15+
Generate valid combinations of balanced parentheses using recursion.
16+
17+
:param partial: A string representing the current combination.
18+
:param open_count: An integer representing the count of open parentheses.
19+
:param close_count: An integer representing the count of close parentheses.
20+
:param n: An integer representing the total number of pairs.
21+
:param result: A list to store valid combinations.
22+
:return: None
23+
24+
This function uses recursion to explore all possible combinations,
25+
ensuring that at each step, the parentheses remain balanced.
26+
27+
Example:
28+
>>> result = []
29+
>>> backtrack("", 0, 0, 2, result)
30+
>>> result
31+
['(())', '()()']
32+
"""
33+
if len(partial) == 2 * n:
34+
# When the combination is complete, add it to the result.
35+
result.append(partial)
36+
return
37+
38+
if open_count < n:
39+
# If we can add an open parenthesis, do so, and recurse.
40+
backtrack(partial + "(", open_count + 1, close_count, n, result)
41+
42+
if close_count < open_count:
43+
# If we can add a close parenthesis (it won't make the combination invalid),
44+
# do so, and recurse.
45+
backtrack(partial + ")", open_count, close_count + 1, n, result)
46+
47+
48+
def generate_parenthesis(n: int) -> list[str]:
49+
"""
50+
Generate valid combinations of balanced parentheses for a given n.
51+
52+
:param n: An integer representing the number of pairs of parentheses.
53+
:return: A list of strings with valid combinations.
54+
55+
This function uses a recursive approach to generate the combinations.
56+
57+
Time Complexity: O(2^(2n)) - In the worst case, we have 2^(2n) combinations.
58+
Space Complexity: O(n) - where 'n' is the number of pairs.
59+
60+
Example 1:
61+
>>> generate_parenthesis(3)
62+
['((()))', '(()())', '(())()', '()(())', '()()()']
63+
64+
Example 2:
65+
>>> generate_parenthesis(1)
66+
['()']
67+
"""
68+
69+
result: list[str] = []
70+
backtrack("", 0, 0, n, result)
71+
return result
72+
73+
74+
if __name__ == "__main__":
75+
import doctest
76+
77+
doctest.testmod()

Diff for: bit_manipulation/find_previous_power_of_two.py

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
def find_previous_power_of_two(number: int) -> int:
2+
"""
3+
Find the largest power of two that is less than or equal to a given integer.
4+
https://stackoverflow.com/questions/1322510
5+
6+
>>> [find_previous_power_of_two(i) for i in range(18)]
7+
[0, 1, 2, 2, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 16, 16]
8+
>>> find_previous_power_of_two(-5)
9+
Traceback (most recent call last):
10+
...
11+
ValueError: Input must be a non-negative integer
12+
>>> find_previous_power_of_two(10.5)
13+
Traceback (most recent call last):
14+
...
15+
ValueError: Input must be a non-negative integer
16+
"""
17+
if not isinstance(number, int) or number < 0:
18+
raise ValueError("Input must be a non-negative integer")
19+
if number == 0:
20+
return 0
21+
power = 1
22+
while power <= number:
23+
power <<= 1 # Equivalent to multiplying by 2
24+
return power >> 1 if number > 1 else 1
25+
26+
27+
if __name__ == "__main__":
28+
import doctest
29+
30+
doctest.testmod()

Diff for: bit_manipulation/missing_number.py

+12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ def find_missing_number(nums: list[int]) -> int:
1111
Example:
1212
>>> find_missing_number([0, 1, 3, 4])
1313
2
14+
>>> find_missing_number([4, 3, 1, 0])
15+
2
16+
>>> find_missing_number([-4, -3, -1, 0])
17+
-2
18+
>>> find_missing_number([-2, 2, 1, 3, 0])
19+
-1
1420
>>> find_missing_number([1, 3, 4, 5, 6])
1521
2
1622
>>> find_missing_number([6, 5, 4, 2, 1])
@@ -26,3 +32,9 @@ def find_missing_number(nums: list[int]) -> int:
2632
missing_number ^= i ^ nums[i - low]
2733

2834
return missing_number
35+
36+
37+
if __name__ == "__main__":
38+
import doctest
39+
40+
doctest.testmod()

Diff for: boolean_algebra/karnaugh_map_simplification.py

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
"""
2+
https://en.wikipedia.org/wiki/Karnaugh_map
3+
https://www.allaboutcircuits.com/technical-articles/karnaugh-map-boolean-algebraic-simplification-technique
4+
"""
5+
6+
7+
def simplify_kmap(kmap: list[list[int]]) -> str:
8+
"""
9+
Simplify the Karnaugh map.
10+
>>> simplify_kmap(kmap=[[0, 1], [1, 1]])
11+
"A'B + AB' + AB"
12+
>>> simplify_kmap(kmap=[[0, 0], [0, 0]])
13+
''
14+
>>> simplify_kmap(kmap=[[0, 1], [1, -1]])
15+
"A'B + AB' + AB"
16+
>>> simplify_kmap(kmap=[[0, 1], [1, 2]])
17+
"A'B + AB' + AB"
18+
>>> simplify_kmap(kmap=[[0, 1], [1, 1.1]])
19+
"A'B + AB' + AB"
20+
>>> simplify_kmap(kmap=[[0, 1], [1, 'a']])
21+
"A'B + AB' + AB"
22+
"""
23+
simplified_f = []
24+
for a, row in enumerate(kmap):
25+
for b, item in enumerate(row):
26+
if item:
27+
term = ("A" if a else "A'") + ("B" if b else "B'")
28+
simplified_f.append(term)
29+
return " + ".join(simplified_f)
30+
31+
32+
def main() -> None:
33+
"""
34+
Main function to create and simplify a K-Map.
35+
36+
>>> main()
37+
[0, 1]
38+
[1, 1]
39+
Simplified Expression:
40+
A'B + AB' + AB
41+
"""
42+
kmap = [[0, 1], [1, 1]]
43+
44+
# Manually generate the product of [0, 1] and [0, 1]
45+
46+
for row in kmap:
47+
print(row)
48+
49+
print("Simplified Expression:")
50+
print(simplify_kmap(kmap))
51+
52+
53+
if __name__ == "__main__":
54+
main()
55+
print(f"{simplify_kmap(kmap=[[0, 1], [1, 1]]) = }")

Diff for: boolean_algebra/multiplexer.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
def mux(input0: int, input1: int, select: int) -> int:
2+
"""
3+
Implement a 2-to-1 Multiplexer.
4+
5+
:param input0: The first input value (0 or 1).
6+
:param input1: The second input value (0 or 1).
7+
:param select: The select signal (0 or 1) to choose between input0 and input1.
8+
:return: The output based on the select signal. input1 if select else input0.
9+
10+
https://www.electrically4u.com/solved-problems-on-multiplexer
11+
https://en.wikipedia.org/wiki/Multiplexer
12+
13+
>>> mux(0, 1, 0)
14+
0
15+
>>> mux(0, 1, 1)
16+
1
17+
>>> mux(1, 0, 0)
18+
1
19+
>>> mux(1, 0, 1)
20+
0
21+
>>> mux(2, 1, 0)
22+
Traceback (most recent call last):
23+
...
24+
ValueError: Inputs and select signal must be 0 or 1
25+
>>> mux(0, -1, 0)
26+
Traceback (most recent call last):
27+
...
28+
ValueError: Inputs and select signal must be 0 or 1
29+
>>> mux(0, 1, 1.1)
30+
Traceback (most recent call last):
31+
...
32+
ValueError: Inputs and select signal must be 0 or 1
33+
"""
34+
if all(i in (0, 1) for i in (input0, input1, select)):
35+
return input1 if select else input0
36+
raise ValueError("Inputs and select signal must be 0 or 1")
37+
38+
39+
if __name__ == "__main__":
40+
import doctest
41+
42+
doctest.testmod()

Diff for: ciphers/running_key_cipher.py

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
https://en.wikipedia.org/wiki/Running_key_cipher
3+
"""
4+
5+
6+
def running_key_encrypt(key: str, plaintext: str) -> str:
7+
"""
8+
Encrypts the plaintext using the Running Key Cipher.
9+
10+
:param key: The running key (long piece of text).
11+
:param plaintext: The plaintext to be encrypted.
12+
:return: The ciphertext.
13+
"""
14+
plaintext = plaintext.replace(" ", "").upper()
15+
key = key.replace(" ", "").upper()
16+
key_length = len(key)
17+
ciphertext = []
18+
ord_a = ord("A")
19+
20+
for i, char in enumerate(plaintext):
21+
p = ord(char) - ord_a
22+
k = ord(key[i % key_length]) - ord_a
23+
c = (p + k) % 26
24+
ciphertext.append(chr(c + ord_a))
25+
26+
return "".join(ciphertext)
27+
28+
29+
def running_key_decrypt(key: str, ciphertext: str) -> str:
30+
"""
31+
Decrypts the ciphertext using the Running Key Cipher.
32+
33+
:param key: The running key (long piece of text).
34+
:param ciphertext: The ciphertext to be decrypted.
35+
:return: The plaintext.
36+
"""
37+
ciphertext = ciphertext.replace(" ", "").upper()
38+
key = key.replace(" ", "").upper()
39+
key_length = len(key)
40+
plaintext = []
41+
ord_a = ord("A")
42+
43+
for i, char in enumerate(ciphertext):
44+
c = ord(char) - ord_a
45+
k = ord(key[i % key_length]) - ord_a
46+
p = (c - k) % 26
47+
plaintext.append(chr(p + ord_a))
48+
49+
return "".join(plaintext)
50+
51+
52+
def test_running_key_encrypt() -> None:
53+
"""
54+
>>> key = "How does the duck know that? said Victor"
55+
>>> ciphertext = running_key_encrypt(key, "DEFEND THIS")
56+
>>> running_key_decrypt(key, ciphertext) == "DEFENDTHIS"
57+
True
58+
"""
59+
60+
61+
if __name__ == "__main__":
62+
import doctest
63+
64+
doctest.testmod()
65+
test_running_key_encrypt()
66+
67+
plaintext = input("Enter the plaintext: ").upper()
68+
print(f"\n{plaintext = }")
69+
70+
key = "How does the duck know that? said Victor"
71+
encrypted_text = running_key_encrypt(key, plaintext)
72+
print(f"{encrypted_text = }")
73+
74+
decrypted_text = running_key_decrypt(key, encrypted_text)
75+
print(f"{decrypted_text = }")

0 commit comments

Comments
 (0)