Compare commits

..

10 Commits

Author SHA1 Message Date
JEONGHYUN MIN
ac5f2accc0
Merge 72eebdeba7 into 6c92c5a539 2025-01-28 16:16:18 +03:00
pre-commit-ci[bot]
6c92c5a539
[pre-commit.ci] pre-commit autoupdate (#12542)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/astral-sh/ruff-pre-commit: v0.9.2 → v0.9.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.2...v0.9.3)
- [github.com/codespell-project/codespell: v2.3.0 → v2.4.0](https://github.com/codespell-project/codespell/compare/v2.3.0...v2.4.0)

* Update trifid_cipher.py

* Update pyproject.toml

* Update trifid_cipher.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Christian Clauss <cclauss@me.com>
2025-01-27 22:05:20 +01:00
Rachel Spears
13e4d3e76c
Fix error in avl_tree del_node function (#11510)
* fixed error in del_node function

* Update avl_tree.py

---------

Co-authored-by: Maxim Smolskiy <mithridatus@mail.ru>
2025-01-24 08:59:36 +03:00
Vijayalaxmi Wakode
c666db3729
Add Doc test bubble sort (#12070)
* The string manipulation - replace()

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update replace.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* updating DIRECTORY.md

* Add doc test to bubble_sort

* Update DIRECTORY.md

* Delete strings/replace.py

* Update bubble_sort.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: vijayalaxmi777 <vijayalaxmi777@users.noreply.github.com>
Co-authored-by: Maxim Smolskiy <mithridatus@mail.ru>
2025-01-24 01:01:47 +03:00
Ronald Ngounou
9fb51b4169
Update docstrings in the functions definitions. (#11797) 2025-01-23 11:02:46 +03:00
pre-commit-ci[bot]
1f74db0c06
[pre-commit.ci] pre-commit autoupdate (#12536)
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.9.1 → v0.9.2](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.1...v0.9.2)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2025-01-20 21:22:02 +01:00
Christian Clauss
91ebea1d99
Sphinx runs on ubuntu 24.04 arm (#12530)
* Speed up our Sphinx GitHub Action with ARM

# `runs-on: ubuntu-24.04-arm`
https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources

* updating DIRECTORY.md

---------

Co-authored-by: cclauss <cclauss@users.noreply.github.com>
2025-01-19 08:33:35 +01:00
Nguyen Thi Thanh Minh
533767ff46
Doomsday Algorithm: Fix leap year check (#12396)
* Fix leap year check

Replace `!=` in `(year % 400) != 0` (line 49) with `==`

Justification: Years that are divisible by 100 (centurian == 100) but not by 400 (year % 400 != 0) are skipped and NOT leap year.

* Update parentheses

Correct the parentheses to make clear the precedence of the conditional check

* Update other/doomsday.py

Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>

---------

Co-authored-by: Tianyi Zheng <tianyizheng02@gmail.com>
2025-01-17 19:07:44 -08:00
aydinomer00
0040ad47f9
Add butterfly pattern implementation (#12493)
* Add butterfly pattern implementation

* Add butterfly pattern implementation

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add finalized butterfly pattern implementation and test

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Delete graphics/test_butterfly_pattern.py

* Update butterfly_pattern.py

* Update butterfly_pattern.py

* Update butterfly_pattern.py

* Update butterfly_pattern.py

* Update butterfly_pattern.py

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Maxim Smolskiy <mithridatus@mail.ru>
2025-01-15 00:24:36 +03:00
Sanjay Muthu
f04d308431
Create longest_increasing_subsequence_iterative.py (#12524)
* Create longest_increasing_subsequence_iterative.py

* Update longest_increasing_subsequence_iterative.py

* Update longest_increasing_subsequence_iterative.py

---------

Co-authored-by: Maxim Smolskiy <mithridatus@mail.ru>
2025-01-14 23:49:04 +03:00
11 changed files with 176 additions and 25 deletions

View File

@ -23,7 +23,7 @@ concurrency:
jobs:
build_docs:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v5

View File

@ -16,13 +16,13 @@ repos:
- id: auto-walrus
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.1
rev: v0.9.3
hooks:
- id: ruff
- id: ruff-format
- repo: https://github.com/codespell-project/codespell
rev: v2.3.0
rev: v2.4.0
hooks:
- id: codespell
additional_dependencies:

View File

@ -377,6 +377,7 @@
* [Longest Common Subsequence](dynamic_programming/longest_common_subsequence.py)
* [Longest Common Substring](dynamic_programming/longest_common_substring.py)
* [Longest Increasing Subsequence](dynamic_programming/longest_increasing_subsequence.py)
* [Longest Increasing Subsequence Iterative](dynamic_programming/longest_increasing_subsequence_iterative.py)
* [Longest Increasing Subsequence O Nlogn](dynamic_programming/longest_increasing_subsequence_o_nlogn.py)
* [Longest Palindromic Subsequence](dynamic_programming/longest_palindromic_subsequence.py)
* [Matrix Chain Multiplication](dynamic_programming/matrix_chain_multiplication.py)
@ -462,6 +463,7 @@
## Graphics
* [Bezier Curve](graphics/bezier_curve.py)
* [Butterfly Pattern](graphics/butterfly_pattern.py)
* [Digital Differential Analyzer Line](graphics/digital_differential_analyzer_line.py)
* [Vector3 For 2D Rendering](graphics/vector3_for_2d_rendering.py)

View File

@ -88,7 +88,7 @@ def __prepare(
...
KeyError: 'Length of alphabet has to be 27.'
Testing with punctuations that are not in the given alphabet
Testing with punctuation not in the given alphabet
>>> __prepare('am i a boy?','abCdeFghijkLmnopqrStuVwxYZ+')
Traceback (most recent call last):
@ -128,7 +128,7 @@ def encrypt_message(
encrypt_message
===============
Encrypts a message using the trifid_cipher. Any punctuatuions that
Encrypts a message using the trifid_cipher. Any punctuatuion chars that
would be used should be added to the alphabet.
PARAMETERS

View File

@ -9,7 +9,9 @@ import time
def cross(items_a, items_b):
"Cross product of elements in A and elements in B."
"""
Cross product of elements in A and elements in B.
"""
return [a + b for a in items_a for b in items_b]
@ -27,7 +29,7 @@ peers = {s: {x for u in units[s] for x in u} - {s} for s in squares}
def test():
"A set of unit tests."
"""A set of unit tests."""
assert len(squares) == 81
assert len(unitlist) == 27
assert all(len(units[s]) == 3 for s in squares)
@ -47,8 +49,10 @@ def test():
def parse_grid(grid):
"""Convert grid to a dict of possible values, {square: digits}, or
return False if a contradiction is detected."""
"""
Convert grid to a dict of possible values, {square: digits}, or
return False if a contradiction is detected.
"""
## To start, every square can be any digit; then assign values from the grid.
values = {s: digits for s in squares}
for s, d in grid_values(grid).items():
@ -58,15 +62,19 @@ def parse_grid(grid):
def grid_values(grid):
"Convert grid into a dict of {square: char} with '0' or '.' for empties."
"""
Convert grid into a dict of {square: char} with '0' or '.' for empties.
"""
chars = [c for c in grid if c in digits or c in "0."]
assert len(chars) == 81
return dict(zip(squares, chars))
def assign(values, s, d):
"""Eliminate all the other values (except d) from values[s] and propagate.
Return values, except return False if a contradiction is detected."""
"""
Eliminate all the other values (except d) from values[s] and propagate.
Return values, except return False if a contradiction is detected.
"""
other_values = values[s].replace(d, "")
if all(eliminate(values, s, d2) for d2 in other_values):
return values
@ -75,8 +83,10 @@ def assign(values, s, d):
def eliminate(values, s, d):
"""Eliminate d from values[s]; propagate when values or places <= 2.
Return values, except return False if a contradiction is detected."""
"""
Eliminate d from values[s]; propagate when values or places <= 2.
Return values, except return False if a contradiction is detected.
"""
if d not in values[s]:
return values ## Already eliminated
values[s] = values[s].replace(d, "")
@ -99,7 +109,9 @@ def eliminate(values, s, d):
def display(values):
"Display these values as a 2-D grid."
"""
Display these values as a 2-D grid.
"""
width = 1 + max(len(values[s]) for s in squares)
line = "+".join(["-" * (width * 3)] * 3)
for r in rows:
@ -114,11 +126,14 @@ def display(values):
def solve(grid):
"""
Solve the grid.
"""
return search(parse_grid(grid))
def some(seq):
"Return some element of seq that is true."
"""Return some element of seq that is true."""
for e in seq:
if e:
return e
@ -126,7 +141,9 @@ def some(seq):
def search(values):
"Using depth-first search and propagation, try all possible values."
"""
Using depth-first search and propagation, try all possible values.
"""
if values is False:
return False ## Failed earlier
if all(len(values[s]) == 1 for s in squares):
@ -137,9 +154,11 @@ def search(values):
def solve_all(grids, name="", showif=0.0):
"""Attempt to solve a sequence of grids. Report results.
"""
Attempt to solve a sequence of grids. Report results.
When showif is a number of seconds, display puzzles that take longer.
When showif is None, don't display any puzzles."""
When showif is None, don't display any puzzles.
"""
def time_solve(grid):
start = time.monotonic()
@ -162,7 +181,9 @@ def solve_all(grids, name="", showif=0.0):
def solved(values):
"A puzzle is solved if each unit is a permutation of the digits 1 to 9."
"""
A puzzle is solved if each unit is a permutation of the digits 1 to 9.
"""
def unitsolved(unit):
return {values[s] for s in unit} == set(digits)
@ -177,9 +198,11 @@ def from_file(filename, sep="\n"):
def random_puzzle(assignments=17):
"""Make a random puzzle with N or more assignments. Restart on contradictions.
"""
Make a random puzzle with N or more assignments. Restart on contradictions.
Note the resulting puzzle is not guaranteed to be solvable, but empirically
about 99.8% of them are solvable. Some have multiple solutions."""
about 99.8% of them are solvable. Some have multiple solutions.
"""
values = {s: digits for s in squares}
for s in shuffled(squares):
if not assign(values, s, random.choice(values[s])):
@ -191,7 +214,9 @@ def random_puzzle(assignments=17):
def shuffled(seq):
"Return a randomly shuffled copy of the input sequence."
"""
Return a randomly shuffled copy of the input sequence.
"""
seq = list(seq)
random.shuffle(seq)
return seq

View File

@ -221,6 +221,10 @@ def del_node(root: MyNode, data: Any) -> MyNode | None:
else:
root.set_right(del_node(right_child, data))
# Re-fetch left_child and right_child references
left_child = root.get_left()
right_child = root.get_right()
if get_height(right_child) - get_height(left_child) == 2:
assert right_child is not None
if get_height(right_child.get_right()) > get_height(right_child.get_left()):

View File

@ -0,0 +1,72 @@
"""
Author : Sanjay Muthu <https://github.com/XenoBytesX>
This is a pure Python implementation of Dynamic Programming solution to the longest
increasing subsequence of a given sequence.
The problem is:
Given an array, to find the longest and increasing sub-array in that given array and
return it.
Example:
``[10, 22, 9, 33, 21, 50, 41, 60, 80]`` as input will return
``[10, 22, 33, 50, 60, 80]`` as output
"""
from __future__ import annotations
import copy
def longest_subsequence(array: list[int]) -> list[int]:
"""
Some examples
>>> longest_subsequence([10, 22, 9, 33, 21, 50, 41, 60, 80])
[10, 22, 33, 50, 60, 80]
>>> longest_subsequence([4, 8, 7, 5, 1, 12, 2, 3, 9])
[1, 2, 3, 9]
>>> longest_subsequence([9, 8, 7, 6, 5, 7])
[7, 7]
>>> longest_subsequence([28, 26, 12, 23, 35, 39])
[12, 23, 35, 39]
>>> longest_subsequence([1, 1, 1])
[1, 1, 1]
>>> longest_subsequence([])
[]
"""
n = len(array)
# The longest increasing subsequence ending at array[i]
longest_increasing_subsequence = []
for i in range(n):
longest_increasing_subsequence.append([array[i]])
for i in range(1, n):
for prev in range(i):
# If array[prev] is less than or equal to array[i], then
# longest_increasing_subsequence[prev] + array[i]
# is a valid increasing subsequence
# longest_increasing_subsequence[i] is only set to
# longest_increasing_subsequence[prev] + array[i] if the length is longer.
if array[prev] <= array[i] and len(
longest_increasing_subsequence[prev]
) + 1 > len(longest_increasing_subsequence[i]):
longest_increasing_subsequence[i] = copy.copy(
longest_increasing_subsequence[prev]
)
longest_increasing_subsequence[i].append(array[i])
result: list[int] = []
for i in range(n):
if len(longest_increasing_subsequence[i]) > len(result):
result = longest_increasing_subsequence[i]
return result
if __name__ == "__main__":
import doctest
doctest.testmod()

View File

@ -0,0 +1,46 @@
def butterfly_pattern(n: int) -> str:
"""
Creates a butterfly pattern of size n and returns it as a string.
>>> print(butterfly_pattern(3))
* *
** **
*****
** **
* *
>>> print(butterfly_pattern(5))
* *
** **
*** ***
**** ****
*********
**** ****
*** ***
** **
* *
"""
result = []
# Upper part
for i in range(1, n):
left_stars = "*" * i
spaces = " " * (2 * (n - i) - 1)
right_stars = "*" * i
result.append(left_stars + spaces + right_stars)
# Middle part
result.append("*" * (2 * n - 1))
# Lower part
for i in range(n - 1, 0, -1):
left_stars = "*" * i
spaces = " " * (2 * (n - i) - 1)
right_stars = "*" * i
result.append(left_stars + spaces + right_stars)
return "\n".join(result)
if __name__ == "__main__":
n = int(input("Enter the size of the butterfly pattern: "))
print(butterfly_pattern(n))

View File

@ -46,7 +46,7 @@ def get_week_day(year: int, month: int, day: int) -> str:
) % 7
day_anchor = (
DOOMSDAY_NOT_LEAP[month - 1]
if (year % 4 != 0) or (centurian == 0 and (year % 400) == 0)
if year % 4 != 0 or (centurian == 0 and year % 400 != 0)
else DOOMSDAY_LEAP[month - 1]
)
week_day = (dooms_day + day - day_anchor) % 7

View File

@ -159,7 +159,7 @@ lint.pylint.max-returns = 8 # default: 6
lint.pylint.max-statements = 88 # default: 50
[tool.codespell]
ignore-words-list = "3rt,ans,bitap,crate,damon,fo,followings,hist,iff,kwanza,manuel,mater,secant,som,sur,tim,toi,zar"
ignore-words-list = "3rt,abd,aer,ans,bitap,crate,damon,fo,followings,hist,iff,kwanza,manuel,mater,secant,som,sur,tim,toi,zar"
skip = "./.*,*.json,*.lock,ciphers/prehistoric_men.txt,project_euler/problem_022/p022_names.txt,pyproject.toml,strings/dictionary.txt,strings/words.txt"
[tool.pytest.ini_options]

View File

@ -85,6 +85,8 @@ def bubble_sort_recursive(collection: list[Any]) -> list[Any]:
[1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7]
>>> bubble_sort_recursive([1, 3.3, 5, 7.7, 2, 4.4, 6])
[1, 2, 3.3, 4.4, 5, 6, 7.7]
>>> bubble_sort_recursive(['a', 'Z', 'B', 'C', 'A', 'c'])
['A', 'B', 'C', 'Z', 'a', 'c']
>>> import random
>>> collection_arg = random.sample(range(-50, 50), 100)
>>> bubble_sort_recursive(collection_arg) == sorted(collection_arg)