forked from TheAlgorithms/Python
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'TheAlgorithms:master' into master
- Loading branch information
Showing
13 changed files
with
654 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
""" | ||
Word Break Problem is a well-known problem in computer science. | ||
Given a string and a dictionary of words, the task is to determine if | ||
the string can be segmented into a sequence of one or more dictionary words. | ||
Wikipedia: https://en.wikipedia.org/wiki/Word_break_problem | ||
""" | ||
|
||
|
||
def backtrack(input_string: str, word_dict: set[str], start: int) -> bool: | ||
""" | ||
Helper function that uses backtracking to determine if a valid | ||
word segmentation is possible starting from index 'start'. | ||
Parameters: | ||
input_string (str): The input string to be segmented. | ||
word_dict (set[str]): A set of valid dictionary words. | ||
start (int): The starting index of the substring to be checked. | ||
Returns: | ||
bool: True if a valid segmentation is possible, otherwise False. | ||
Example: | ||
>>> backtrack("leetcode", {"leet", "code"}, 0) | ||
True | ||
>>> backtrack("applepenapple", {"apple", "pen"}, 0) | ||
True | ||
>>> backtrack("catsandog", {"cats", "dog", "sand", "and", "cat"}, 0) | ||
False | ||
""" | ||
|
||
# Base case: if the starting index has reached the end of the string | ||
if start == len(input_string): | ||
return True | ||
|
||
# Try every possible substring from 'start' to 'end' | ||
for end in range(start + 1, len(input_string) + 1): | ||
if input_string[start:end] in word_dict and backtrack( | ||
input_string, word_dict, end | ||
): | ||
return True | ||
|
||
return False | ||
|
||
|
||
def word_break(input_string: str, word_dict: set[str]) -> bool: | ||
""" | ||
Determines if the input string can be segmented into a sequence of | ||
valid dictionary words using backtracking. | ||
Parameters: | ||
input_string (str): The input string to segment. | ||
word_dict (set[str]): The set of valid words. | ||
Returns: | ||
bool: True if the string can be segmented into valid words, otherwise False. | ||
Example: | ||
>>> word_break("leetcode", {"leet", "code"}) | ||
True | ||
>>> word_break("applepenapple", {"apple", "pen"}) | ||
True | ||
>>> word_break("catsandog", {"cats", "dog", "sand", "and", "cat"}) | ||
False | ||
""" | ||
|
||
return backtrack(input_string, word_dict, 0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from string import ascii_uppercase | ||
|
||
|
||
def gronsfeld(text: str, key: str) -> str: | ||
""" | ||
Encrypt plaintext with the Gronsfeld cipher | ||
>>> gronsfeld('hello', '412') | ||
'LFNPP' | ||
>>> gronsfeld('hello', '123') | ||
'IGOMQ' | ||
>>> gronsfeld('', '123') | ||
'' | ||
>>> gronsfeld('yes, ¥€$ - _!@#%?', '0') | ||
'YES, ¥€$ - _!@#%?' | ||
>>> gronsfeld('yes, ¥€$ - _!@#%?', '01') | ||
'YFS, ¥€$ - _!@#%?' | ||
>>> gronsfeld('yes, ¥€$ - _!@#%?', '012') | ||
'YFU, ¥€$ - _!@#%?' | ||
>>> gronsfeld('yes, ¥€$ - _!@#%?', '') | ||
Traceback (most recent call last): | ||
... | ||
ZeroDivisionError: integer modulo by zero | ||
""" | ||
ascii_len = len(ascii_uppercase) | ||
key_len = len(key) | ||
encrypted_text = "" | ||
keys = [int(char) for char in key] | ||
upper_case_text = text.upper() | ||
|
||
for i, char in enumerate(upper_case_text): | ||
if char in ascii_uppercase: | ||
new_position = (ascii_uppercase.index(char) + keys[i % key_len]) % ascii_len | ||
shifted_letter = ascii_uppercase[new_position] | ||
encrypted_text += shifted_letter | ||
else: | ||
encrypted_text += char | ||
|
||
return encrypted_text | ||
|
||
|
||
if __name__ == "__main__": | ||
from doctest import testmod | ||
|
||
testmod() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
from __future__ import annotations | ||
|
||
import sys | ||
from dataclasses import dataclass | ||
|
||
INT_MIN = -sys.maxsize + 1 | ||
INT_MAX = sys.maxsize - 1 | ||
|
||
|
||
@dataclass | ||
class TreeNode: | ||
val: int = 0 | ||
left: TreeNode | None = None | ||
right: TreeNode | None = None | ||
|
||
|
||
def max_sum_bst(root: TreeNode | None) -> int: | ||
""" | ||
The solution traverses a binary tree to find the maximum sum of | ||
keys in any subtree that is a Binary Search Tree (BST). It uses | ||
recursion to validate BST properties and calculates sums, returning | ||
the highest sum found among all valid BST subtrees. | ||
>>> t1 = TreeNode(4) | ||
>>> t1.left = TreeNode(3) | ||
>>> t1.left.left = TreeNode(1) | ||
>>> t1.left.right = TreeNode(2) | ||
>>> print(max_sum_bst(t1)) | ||
2 | ||
>>> t2 = TreeNode(-4) | ||
>>> t2.left = TreeNode(-2) | ||
>>> t2.right = TreeNode(-5) | ||
>>> print(max_sum_bst(t2)) | ||
0 | ||
>>> t3 = TreeNode(1) | ||
>>> t3.left = TreeNode(4) | ||
>>> t3.left.left = TreeNode(2) | ||
>>> t3.left.right = TreeNode(4) | ||
>>> t3.right = TreeNode(3) | ||
>>> t3.right.left = TreeNode(2) | ||
>>> t3.right.right = TreeNode(5) | ||
>>> t3.right.right.left = TreeNode(4) | ||
>>> t3.right.right.right = TreeNode(6) | ||
>>> print(max_sum_bst(t3)) | ||
20 | ||
""" | ||
ans: int = 0 | ||
|
||
def solver(node: TreeNode | None) -> tuple[bool, int, int, int]: | ||
""" | ||
Returns the maximum sum by making recursive calls | ||
>>> t1 = TreeNode(1) | ||
>>> print(solver(t1)) | ||
1 | ||
""" | ||
nonlocal ans | ||
|
||
if not node: | ||
return True, INT_MAX, INT_MIN, 0 # Valid BST, min, max, sum | ||
|
||
is_left_valid, min_left, max_left, sum_left = solver(node.left) | ||
is_right_valid, min_right, max_right, sum_right = solver(node.right) | ||
|
||
if is_left_valid and is_right_valid and max_left < node.val < min_right: | ||
total_sum = sum_left + sum_right + node.val | ||
ans = max(ans, total_sum) | ||
return True, min(min_left, node.val), max(max_right, node.val), total_sum | ||
|
||
return False, -1, -1, -1 # Not a valid BST | ||
|
||
solver(root) | ||
return ans | ||
|
||
|
||
if __name__ == "__main__": | ||
import doctest | ||
|
||
doctest.testmod() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
from collections.abc import Iterator | ||
|
||
|
||
def lexical_order(max_number: int) -> Iterator[int]: | ||
""" | ||
Generate numbers in lexical order from 1 to max_number. | ||
>>> " ".join(map(str, lexical_order(13))) | ||
'1 10 11 12 13 2 3 4 5 6 7 8 9' | ||
>>> list(lexical_order(1)) | ||
[1] | ||
>>> " ".join(map(str, lexical_order(20))) | ||
'1 10 11 12 13 14 15 16 17 18 19 2 20 3 4 5 6 7 8 9' | ||
>>> " ".join(map(str, lexical_order(25))) | ||
'1 10 11 12 13 14 15 16 17 18 19 2 20 21 22 23 24 25 3 4 5 6 7 8 9' | ||
>>> list(lexical_order(12)) | ||
[1, 10, 11, 12, 2, 3, 4, 5, 6, 7, 8, 9] | ||
""" | ||
|
||
stack = [1] | ||
|
||
while stack: | ||
num = stack.pop() | ||
if num > max_number: | ||
continue | ||
|
||
yield num | ||
if (num % 10) != 9: | ||
stack.append(num + 1) | ||
|
||
stack.append(num * 10) | ||
|
||
|
||
if __name__ == "__main__": | ||
from doctest import testmod | ||
|
||
testmod() | ||
print(f"Numbers from 1 to 25 in lexical order: {list(lexical_order(26))}") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.