Skip to content

Commit bac7229

Browse files
authored
Merge branch 'master' into add-evil-number
2 parents c83dd55 + b1cf505 commit bac7229

64 files changed

Lines changed: 4294 additions & 519 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎CONTRIBUTING.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ Comments which are not on the same line as code should appear ___before___ the c
196196
return a + b
197197
```
198198

199-
[Install ty](https://docs.astral.sh/ty/installation/) and then pslease use the command `ty check` to test all files or `ty check path/to/file.py` to test a specific file.
199+
[Install ty](https://docs.astral.sh/ty/installation/) and then please use the command `ty check` to test all files or `ty check path/to/file.py` to test a specific file.
200200

201201
- [__List comprehensions and generators__](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions) are preferred over the use of `lambda`, `map`, `filter`, `reduce` but the important thing is to demonstrate the power of Python in code that is easy to read and maintain.
202202

‎DIRECTORY.md‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,17 @@
146146
* [Baconian Cipher](ciphers/baconian_cipher.py)
147147
* [Base16](ciphers/base16.py)
148148
* [Base32](ciphers/base32.py)
149+
* [Base58](ciphers/base58.py)
149150
* [Base64 Cipher](ciphers/base64_cipher.py)
150151
* [Base85](ciphers/base85.py)
151152
* [Beaufort Cipher](ciphers/beaufort_cipher.py)
152153
* [Bifid](ciphers/bifid.py)
153154
* [Brute Force Caesar Cipher](ciphers/brute_force_caesar_cipher.py)
154155
* [Caesar Cipher](ciphers/caesar_cipher.py)
156+
* [Columnar Transposition](ciphers/columnar_transposition.py)
155157
* [Cryptomath Module](ciphers/cryptomath_module.py)
156158
* [Decrypt Caesar With Chi Squared](ciphers/decrypt_caesar_with_chi_squared.py)
159+
* [Des Ecb](ciphers/des_ecb.py)
157160
* [Deterministic Miller Rabin](ciphers/deterministic_miller_rabin.py)
158161
* [Diffie](ciphers/diffie.py)
159162
* [Diffie Hellman](ciphers/diffie_hellman.py)
@@ -181,6 +184,7 @@
181184
* [Shuffled Shift Cipher](ciphers/shuffled_shift_cipher.py)
182185
* [Simple Keyword Cypher](ciphers/simple_keyword_cypher.py)
183186
* [Simple Substitution Cipher](ciphers/simple_substitution_cipher.py)
187+
* [Skytale Cipher](ciphers/skytale_cipher.py)
184188
* [Transposition Cipher](ciphers/transposition_cipher.py)
185189
* [Transposition Cipher Encrypt Decrypt File](ciphers/transposition_cipher_encrypt_decrypt_file.py)
186190
* [Trifid Cipher](ciphers/trifid_cipher.py)
@@ -205,6 +209,7 @@
205209

206210
## [Conversions](conversions)
207211
* [Astronomical Length Scale Conversion](conversions/astronomical_length_scale_conversion.py)
212+
* [Base64 To Binary](conversions/base64_to_binary.py)
208213
* [Binary To Decimal](conversions/binary_to_decimal.py)
209214
* [Binary To Excess3](conversions/binary_to_excess3.py)
210215
* [Binary To Gray](conversions/binary_to_gray.py)
@@ -220,6 +225,7 @@
220225
* [Energy Conversions](conversions/energy_conversions.py)
221226
* [Excel Title To Column](conversions/excel_title_to_column.py)
222227
* [Hex To Bin](conversions/hex_to_bin.py)
228+
* [Hex To Rgb](conversions/hex_to_rgb.py)
223229
* [Hexadecimal To Decimal](conversions/hexadecimal_to_decimal.py)
224230
* [Int To Negative Binary Base](conversions/int_to_negative_binary_base.py)
225231
* [Ipv4 Conversion](conversions/ipv4_conversion.py)
@@ -510,6 +516,7 @@
510516
* [Ic 555 Timer](electronics/ic_555_timer.py)
511517
* [Ind Reactance](electronics/ind_reactance.py)
512518
* [Ohms Law](electronics/ohms_law.py)
519+
* [Power Factor Correction](electronics/power_factor_correction.py)
513520
* [Real And Reactive Power](electronics/real_and_reactive_power.py)
514521
* [Resistor Color Code](electronics/resistor_color_code.py)
515522
* [Resistor Equivalence](electronics/resistor_equivalence.py)
@@ -527,6 +534,7 @@
527534
* [Exponential Moving Average](financial/exponential_moving_average.py)
528535
* [Interest](financial/interest.py)
529536
* [Kelly Criterion](financial/kelly_criterion.py)
537+
* [Macaulay Duration](financial/macaulay_duration.py)
530538
* [Present Value](financial/present_value.py)
531539
* [Price Plus Tax](financial/price_plus_tax.py)
532540
* [Sharpe Ratio](financial/sharpe_ratio.py)
@@ -741,6 +749,7 @@
741749
* [Q Learning](machine_learning/q_learning.py)
742750
* [Random Forest Classifier](machine_learning/random_forest_classifier.py)
743751
* [Random Forest Regressor](machine_learning/random_forest_regressor.py)
752+
* [Ridge Regression](machine_learning/ridge_regression.py)
744753
* [Rmsprop](machine_learning/rmsprop.py)
745754
* [Scoring Functions](machine_learning/scoring_functions.py)
746755
* [Self Organizing Map](machine_learning/self_organizing_map.py)
@@ -1009,6 +1018,7 @@
10091018
* [Scaled Exponential Linear Unit](neural_network/activation_functions/scaled_exponential_linear_unit.py)
10101019
* [Soboleva Modified Hyperbolic Tangent](neural_network/activation_functions/soboleva_modified_hyperbolic_tangent.py)
10111020
* [Softplus](neural_network/activation_functions/softplus.py)
1021+
* [Softsign](neural_network/activation_functions/softsign.py)
10121022
* [Squareplus](neural_network/activation_functions/squareplus.py)
10131023
* [Swish](neural_network/activation_functions/swish.py)
10141024
* [Back Propagation Neural Network](neural_network/back_propagation_neural_network.py)
@@ -1161,6 +1171,7 @@
11611171
* [Sol2](project_euler/problem_012/sol2.py)
11621172
* Problem 013
11631173
* [Sol1](project_euler/problem_013/sol1.py)
1174+
* [Sol2](project_euler/problem_013/sol2.py)
11641175
* Problem 014
11651176
* [Sol1](project_euler/problem_014/sol1.py)
11661177
* [Sol2](project_euler/problem_014/sol2.py)
@@ -1264,6 +1275,8 @@
12641275
* [Sol1](project_euler/problem_058/sol1.py)
12651276
* Problem 059
12661277
* [Sol1](project_euler/problem_059/sol1.py)
1278+
* Problem 060
1279+
* [Sol1](project_euler/problem_060/sol1.py)
12671280
* Problem 062
12681281
* [Sol1](project_euler/problem_062/sol1.py)
12691282
* Problem 063
@@ -1339,6 +1352,8 @@
13391352
* [Sol1](project_euler/problem_107/sol1.py)
13401353
* Problem 109
13411354
* [Sol1](project_euler/problem_109/sol1.py)
1355+
* Problem 111
1356+
* [Sol1](project_euler/problem_111/sol1.py)
13421357
* Problem 112
13431358
* [Sol1](project_euler/problem_112/sol1.py)
13441359
* Problem 113
@@ -1361,6 +1376,8 @@
13611376
* [Sol1](project_euler/problem_122/sol1.py)
13621377
* Problem 123
13631378
* [Sol1](project_euler/problem_123/sol1.py)
1379+
* Problem 124
1380+
* [Sol1](project_euler/problem_124/sol1.py)
13641381
* Problem 125
13651382
* [Sol1](project_euler/problem_125/sol1.py)
13661383
* Problem 129
@@ -1371,6 +1388,12 @@
13711388
* [Sol1](project_euler/problem_135/sol1.py)
13721389
* Problem 136
13731390
* [Sol1](project_euler/problem_136/sol1.py)
1391+
* Problem 137
1392+
* [Sol1](project_euler/problem_137/sol1.py)
1393+
* Problem 138
1394+
* [Sol1](project_euler/problem_138/sol1.py)
1395+
* Problem 142
1396+
* [Sol1](project_euler/problem_142/sol1.py)
13741397
* Problem 144
13751398
* [Sol1](project_euler/problem_144/sol1.py)
13761399
* Problem 145
@@ -1521,6 +1544,7 @@
15211544
* [Booths Algorithm](strings/booths_algorithm.py)
15221545
* [Boyer Moore Horspool](strings/boyer_moore_horspool.py)
15231546
* [Boyer Moore Search](strings/boyer_moore_search.py)
1547+
* [Bpe Tokenizer](strings/bpe_tokenizer.py)
15241548
* [Camel Case To Snake Case](strings/camel_case_to_snake_case.py)
15251549
* [Can String Be Rearranged As Palindrome](strings/can_string_be_rearranged_as_palindrome.py)
15261550
* [Capitalize](strings/capitalize.py)
@@ -1537,6 +1561,7 @@
15371561
* [Indian Phone Validator](strings/indian_phone_validator.py)
15381562
* [Is Contains Unique Chars](strings/is_contains_unique_chars.py)
15391563
* [Is Isogram](strings/is_isogram.py)
1564+
* [Is Isomorphic](strings/is_isomorphic.py)
15401565
* [Is Pangram](strings/is_pangram.py)
15411566
* [Is Polish National Id](strings/is_polish_national_id.py)
15421567
* [Is Spain National Id](strings/is_spain_national_id.py)

‎backtracking/crossword_puzzle_solver.py‎

Lines changed: 66 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,28 @@ def is_valid(
66
) -> bool:
77
"""
88
Check if a word can be placed at the given position.
9+
A cell is valid if it is empty or already contains the correct letter
10+
(enabling crossing/intersection between words).
911
10-
>>> puzzle = [
11-
... ['', '', '', ''],
12-
... ['', '', '', ''],
13-
... ['', '', '', ''],
14-
... ['', '', '', '']
15-
... ]
12+
>>> puzzle = [['', '', '', ''], ['', '', '', ''],
13+
... ['', '', '', ''], ['', '', '', '']]
1614
>>> is_valid(puzzle, 'word', 0, 0, True)
1715
True
18-
>>> puzzle = [
19-
... ['', '', '', ''],
20-
... ['', '', '', ''],
21-
... ['', '', '', ''],
22-
... ['', '', '', '']
23-
... ]
2416
>>> is_valid(puzzle, 'word', 0, 0, False)
2517
True
18+
>>> puzzle2 = [['w', '', ''], ['o', '', ''], ['r', '', ''], ['d', '', '']]
19+
>>> is_valid(puzzle2, 'word', 0, 0, True)
20+
True
21+
>>> is_valid(puzzle2, 'cat', 0, 0, True)
22+
False
2623
"""
27-
for i in range(len(word)):
28-
if vertical:
29-
if row + i >= len(puzzle) or puzzle[row + i][col] != "":
30-
return False
31-
elif col + i >= len(puzzle[0]) or puzzle[row][col + i] != "":
24+
rows, cols = len(puzzle), len(puzzle[0])
25+
for i, ch in enumerate(word):
26+
r, c = (row + i, col) if vertical else (row, col + i)
27+
if r >= rows or c >= cols:
28+
return False
29+
cell = puzzle[r][c]
30+
if cell not in ("", ch):
3231
return False
3332
return True
3433

@@ -37,95 +36,87 @@ def place_word(
3736
puzzle: list[list[str]], word: str, row: int, col: int, vertical: bool
3837
) -> None:
3938
"""
40-
Place a word at the given position.
41-
42-
>>> puzzle = [
43-
... ['', '', '', ''],
44-
... ['', '', '', ''],
45-
... ['', '', '', ''],
46-
... ['', '', '', '']
47-
... ]
39+
Place a word at the given position in the puzzle.
40+
41+
>>> puzzle = [['', '', '', ''], ['', '', '', ''],
42+
... ['', '', '', ''], ['', '', '', '']]
4843
>>> place_word(puzzle, 'word', 0, 0, True)
4944
>>> puzzle
5045
[['w', '', '', ''], ['o', '', '', ''], ['r', '', '', ''], ['d', '', '', '']]
5146
"""
52-
for i, char in enumerate(word):
47+
for i, ch in enumerate(word):
5348
if vertical:
54-
puzzle[row + i][col] = char
49+
puzzle[row + i][col] = ch
5550
else:
56-
puzzle[row][col + i] = char
51+
puzzle[row][col + i] = ch
5752

5853

5954
def remove_word(
60-
puzzle: list[list[str]], word: str, row: int, col: int, vertical: bool
55+
puzzle: list[list[str]],
56+
word: str,
57+
row: int,
58+
col: int,
59+
vertical: bool,
60+
snapshot: list[list[str]],
6161
) -> None:
6262
"""
63-
Remove a word from the given position.
64-
65-
>>> puzzle = [
66-
... ['w', '', '', ''],
67-
... ['o', '', '', ''],
68-
... ['r', '', '', ''],
69-
... ['d', '', '', '']
70-
... ]
71-
>>> remove_word(puzzle, 'word', 0, 0, True)
63+
Remove a word from the puzzle, restoring only cells that were empty
64+
before placement. Cells shared with crossing words are preserved.
65+
66+
>>> puzzle = [['w', 'o', 'r', 'd'], ['', '', '', ''],
67+
... ['', '', '', ''], ['', '', '', '']]
68+
>>> snap = [['', 'o', 'r', 'd'], ['', '', '', ''],
69+
... ['', '', '', ''], ['', '', '', '']]
70+
>>> remove_word(puzzle, 'word', 0, 0, False, snap)
7271
>>> puzzle
73-
[['', '', '', ''], ['', '', '', ''], ['', '', '', ''], ['', '', '', '']]
72+
[['', 'o', 'r', 'd'], ['', '', '', ''], ['', '', '', ''], ['', '', '', '']]
7473
"""
7574
for i in range(len(word)):
76-
if vertical:
77-
puzzle[row + i][col] = ""
78-
else:
79-
puzzle[row][col + i] = ""
75+
r, c = (row + i, col) if vertical else (row, col + i)
76+
if snapshot[r][c] == "":
77+
puzzle[r][c] = ""
8078

8179

8280
def solve_crossword(puzzle: list[list[str]], words: list[str]) -> bool:
8381
"""
8482
Solve the crossword puzzle using backtracking.
83+
Words are tried longest-first to prune the search space early.
84+
Intersections between words (shared letters) are supported.
8585
86-
>>> puzzle = [
87-
... ['', '', '', ''],
88-
... ['', '', '', ''],
89-
... ['', '', '', ''],
90-
... ['', '', '', '']
91-
... ]
92-
93-
>>> words = ['word', 'four', 'more', 'last']
94-
>>> solve_crossword(puzzle, words)
86+
>>> puzzle = [['', '', '', ''], ['', '', '', ''],
87+
... ['', '', '', ''], ['', '', '', '']]
88+
>>> solve_crossword(puzzle, ['word', 'four', 'more', 'last'])
9589
True
96-
>>> puzzle = [
97-
... ['', '', '', ''],
98-
... ['', '', '', ''],
99-
... ['', '', '', ''],
100-
... ['', '', '', '']
101-
... ]
102-
>>> words = ['word', 'four', 'more', 'paragraphs']
103-
>>> solve_crossword(puzzle, words)
90+
>>> puzzle2 = [['', '', '', ''], ['', '', '', ''],
91+
... ['', '', '', ''], ['', '', '', '']]
92+
>>> solve_crossword(puzzle2, ['word', 'four', 'more', 'paragraphs'])
10493
False
10594
"""
95+
if not words:
96+
return True
97+
98+
remaining = sorted(words, key=len, reverse=True)
99+
word, rest = remaining[0], remaining[1:]
100+
106101
for row in range(len(puzzle)):
107102
for col in range(len(puzzle[0])):
108-
if puzzle[row][col] == "":
109-
for word in words:
110-
for vertical in [True, False]:
111-
if is_valid(puzzle, word, row, col, vertical):
112-
place_word(puzzle, word, row, col, vertical)
113-
words.remove(word)
114-
if solve_crossword(puzzle, words):
115-
return True
116-
words.append(word)
117-
remove_word(puzzle, word, row, col, vertical)
118-
return False
119-
return True
103+
for vertical in (True, False):
104+
if is_valid(puzzle, word, row, col, vertical):
105+
snapshot = [r[:] for r in puzzle]
106+
place_word(puzzle, word, row, col, vertical)
107+
if solve_crossword(puzzle, rest):
108+
return True
109+
remove_word(puzzle, word, row, col, vertical, snapshot)
110+
111+
return False
120112

121113

122114
if __name__ == "__main__":
123115
PUZZLE = [[""] * 3 for _ in range(3)]
124116
WORDS = ["cat", "dog", "car"]
125-
126117
if solve_crossword(PUZZLE, WORDS):
127118
print("Solution found:")
128119
for row in PUZZLE:
129-
print(" ".join(row))
120+
print(" ".join(cell or "." for cell in row))
130121
else:
131-
print("No solution found:")
122+
print("No solution found.")

0 commit comments

Comments
 (0)