Skip to content

Commit f03d77a

Browse files
authored
Merge branch 'TheAlgorithms:master' into game_of_life_tests
2 parents ff2b4e2 + 0040ad4 commit f03d77a

File tree

130 files changed

+3740
-1047
lines changed

Some content is hidden

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

130 files changed

+3740
-1047
lines changed

.github/workflows/build.yml

+6-9
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,18 @@ jobs:
1010
runs-on: ubuntu-latest
1111
steps:
1212
- uses: actions/checkout@v4
13+
- uses: astral-sh/setup-uv@v5
14+
with:
15+
enable-cache: true
16+
cache-dependency-glob: uv.lock
1317
- uses: actions/setup-python@v5
1418
with:
1519
python-version: 3.13
1620
allow-prereleases: true
17-
- uses: actions/cache@v4
18-
with:
19-
path: ~/.cache/pip
20-
key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }}
21-
- name: Install dependencies
22-
run: |
23-
python -m pip install --upgrade pip setuptools wheel
24-
python -m pip install pytest-cov -r requirements.txt
21+
- run: uv sync --group=test
2522
- name: Run tests
2623
# TODO: #8818 Re-enable quantum tests
27-
run: pytest
24+
run: uv run pytest
2825
--ignore=computer_vision/cnn_classification.py
2926
--ignore=docs/conf.py
3027
--ignore=dynamic_programming/k_means_clustering_tensorflow.py

.github/workflows/project_euler.yml

+6-10
Original file line numberDiff line numberDiff line change
@@ -15,25 +15,21 @@ jobs:
1515
runs-on: ubuntu-latest
1616
steps:
1717
- uses: actions/checkout@v4
18+
- uses: astral-sh/setup-uv@v5
1819
- uses: actions/setup-python@v5
1920
with:
2021
python-version: 3.x
21-
- name: Install pytest and pytest-cov
22-
run: |
23-
python -m pip install --upgrade pip
24-
python -m pip install --upgrade numpy pytest pytest-cov
25-
- run: pytest --doctest-modules --cov-report=term-missing:skip-covered --cov=project_euler/ project_euler/
22+
- run: uv sync --group=euler-validate --group=test
23+
- run: uv run pytest --doctest-modules --cov-report=term-missing:skip-covered --cov=project_euler/ project_euler/
2624
validate-solutions:
2725
runs-on: ubuntu-latest
2826
steps:
2927
- uses: actions/checkout@v4
28+
- uses: astral-sh/setup-uv@v5
3029
- uses: actions/setup-python@v5
3130
with:
3231
python-version: 3.x
33-
- name: Install pytest and requests
34-
run: |
35-
python -m pip install --upgrade pip
36-
python -m pip install --upgrade numpy pytest requests
37-
- run: pytest scripts/validate_solutions.py
32+
- run: uv sync --group=euler-validate --group=test
33+
- run: uv run pytest scripts/validate_solutions.py
3834
env:
3935
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/ruff.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ jobs:
1212
runs-on: ubuntu-latest
1313
steps:
1414
- uses: actions/checkout@v4
15-
- run: pip install --user ruff
16-
- run: ruff check --output-format=github .
15+
- uses: astral-sh/setup-uv@v5
16+
- run: uvx ruff check --output-format=github .

.github/workflows/sphinx.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ jobs:
2626
runs-on: ubuntu-latest
2727
steps:
2828
- uses: actions/checkout@v4
29+
- uses: astral-sh/setup-uv@v5
2930
- uses: actions/setup-python@v5
3031
with:
3132
python-version: 3.13
3233
allow-prereleases: true
33-
- run: pip install --upgrade pip
34-
- run: pip install myst-parser sphinx-autoapi sphinx-pyproject
34+
- run: uv sync --group=docs
3535
- uses: actions/configure-pages@v5
36-
- run: sphinx-build -c docs . docs/_build/html
36+
- run: uv run sphinx-build -c docs . docs/_build/html
3737
- uses: actions/upload-pages-artifact@v3
3838
with:
3939
path: docs/_build/html

.pre-commit-config.yaml

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ repos:
1616
- id: auto-walrus
1717

1818
- repo: https://github.com/astral-sh/ruff-pre-commit
19-
rev: v0.7.0
19+
rev: v0.9.1
2020
hooks:
2121
- id: ruff
2222
- id: ruff-format
@@ -29,7 +29,7 @@ repos:
2929
- tomli
3030

3131
- repo: https://github.com/tox-dev/pyproject-fmt
32-
rev: "2.4.3"
32+
rev: "v2.5.0"
3333
hooks:
3434
- id: pyproject-fmt
3535

@@ -42,12 +42,12 @@ repos:
4242
pass_filenames: false
4343

4444
- repo: https://github.com/abravalheri/validate-pyproject
45-
rev: v0.21
45+
rev: v0.23
4646
hooks:
4747
- id: validate-pyproject
4848

4949
- repo: https://github.com/pre-commit/mirrors-mypy
50-
rev: v1.12.1
50+
rev: v1.14.1
5151
hooks:
5252
- id: mypy
5353
args:

DIRECTORY.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
* [Baconian Cipher](ciphers/baconian_cipher.py)
8787
* [Base16](ciphers/base16.py)
8888
* [Base32](ciphers/base32.py)
89-
* [Base64](ciphers/base64.py)
89+
* [Base64 Cipher](ciphers/base64_cipher.py)
9090
* [Base85](ciphers/base85.py)
9191
* [Beaufort Cipher](ciphers/beaufort_cipher.py)
9292
* [Bifid](ciphers/bifid.py)
@@ -142,6 +142,7 @@
142142
* [Haralick Descriptors](computer_vision/haralick_descriptors.py)
143143
* [Harris Corner](computer_vision/harris_corner.py)
144144
* [Horn Schunck](computer_vision/horn_schunck.py)
145+
* [Intensity Based Segmentation](computer_vision/intensity_based_segmentation.py)
145146
* [Mean Threshold](computer_vision/mean_threshold.py)
146147
* [Mosaic Augmentation](computer_vision/mosaic_augmentation.py)
147148
* [Pooling Functions](computer_vision/pooling_functions.py)
@@ -169,6 +170,7 @@
169170
* [Prefix Conversions](conversions/prefix_conversions.py)
170171
* [Prefix Conversions String](conversions/prefix_conversions_string.py)
171172
* [Pressure Conversions](conversions/pressure_conversions.py)
173+
* [Rectangular To Polar](conversions/rectangular_to_polar.py)
172174
* [Rgb Cmyk Conversion](conversions/rgb_cmyk_conversion.py)
173175
* [Rgb Hsv Conversion](conversions/rgb_hsv_conversion.py)
174176
* [Roman Numerals](conversions/roman_numerals.py)
@@ -460,6 +462,7 @@
460462

461463
## Graphics
462464
* [Bezier Curve](graphics/bezier_curve.py)
465+
* [Digital Differential Analyzer Line](graphics/digital_differential_analyzer_line.py)
463466
* [Vector3 For 2D Rendering](graphics/vector3_for_2d_rendering.py)
464467

465468
## Graphs
@@ -506,6 +509,7 @@
506509
* [Kahns Algorithm Long](graphs/kahns_algorithm_long.py)
507510
* [Kahns Algorithm Topo](graphs/kahns_algorithm_topo.py)
508511
* [Karger](graphs/karger.py)
512+
* [Lanczos Eigenvectors](graphs/lanczos_eigenvectors.py)
509513
* [Markov Chain](graphs/markov_chain.py)
510514
* [Matching Min Vertex Cover](graphs/matching_min_vertex_cover.py)
511515
* [Minimum Path Sum](graphs/minimum_path_sum.py)
@@ -660,6 +664,7 @@
660664
* [Gamma](maths/gamma.py)
661665
* [Gaussian](maths/gaussian.py)
662666
* [Gcd Of N Numbers](maths/gcd_of_n_numbers.py)
667+
* [Geometric Mean](maths/geometric_mean.py)
663668
* [Germain Primes](maths/germain_primes.py)
664669
* [Greatest Common Divisor](maths/greatest_common_divisor.py)
665670
* [Hardy Ramanujanalgo](maths/hardy_ramanujanalgo.py)
@@ -794,6 +799,7 @@
794799
* [Cramers Rule 2X2](matrix/cramers_rule_2x2.py)
795800
* [Inverse Of Matrix](matrix/inverse_of_matrix.py)
796801
* [Largest Square Area In Matrix](matrix/largest_square_area_in_matrix.py)
802+
* [Matrix Based Game](matrix/matrix_based_game.py)
797803
* [Matrix Class](matrix/matrix_class.py)
798804
* [Matrix Equalization](matrix/matrix_equalization.py)
799805
* [Matrix Multiplication Recursion](matrix/matrix_multiplication_recursion.py)
@@ -884,6 +890,7 @@
884890
* [N Body Simulation](physics/n_body_simulation.py)
885891
* [Newtons Law Of Gravitation](physics/newtons_law_of_gravitation.py)
886892
* [Newtons Second Law Of Motion](physics/newtons_second_law_of_motion.py)
893+
* [Period Of Pendulum](physics/period_of_pendulum.py)
887894
* [Photoelectric Effect](physics/photoelectric_effect.py)
888895
* [Potential Energy](physics/potential_energy.py)
889896
* [Rainfall Intensity](physics/rainfall_intensity.py)
@@ -1324,7 +1331,7 @@
13241331
* [Title](strings/title.py)
13251332
* [Top K Frequent Words](strings/top_k_frequent_words.py)
13261333
* [Upper](strings/upper.py)
1327-
* [Wave](strings/wave.py)
1334+
* [Wave String](strings/wave_string.py)
13281335
* [Wildcard Pattern Matching](strings/wildcard_pattern_matching.py)
13291336
* [Word Occurrence](strings/word_occurrence.py)
13301337
* [Word Patterns](strings/word_patterns.py)

audio_filters/iir_filter.py

+19-13
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@ class IIRFilter:
1010
1111
Implementation details:
1212
Based on the 2nd-order function from
13-
https://en.wikipedia.org/wiki/Digital_biquad_filter,
13+
https://en.wikipedia.org/wiki/Digital_biquad_filter,
1414
this generalized N-order function was made.
1515
1616
Using the following transfer function
17-
H(z)=\frac{b_{0}+b_{1}z^{-1}+b_{2}z^{-2}+...+b_{k}z^{-k}}{a_{0}+a_{1}z^{-1}+a_{2}z^{-2}+...+a_{k}z^{-k}}
17+
.. math:: H(z)=\frac{b_{0}+b_{1}z^{-1}+b_{2}z^{-2}+...+b_{k}z^{-k}}
18+
{a_{0}+a_{1}z^{-1}+a_{2}z^{-2}+...+a_{k}z^{-k}}
19+
1820
we can rewrite this to
19-
y[n]={\frac{1}{a_{0}}}\left(\left(b_{0}x[n]+b_{1}x[n-1]+b_{2}x[n-2]+...+b_{k}x[n-k]\right)-\left(a_{1}y[n-1]+a_{2}y[n-2]+...+a_{k}y[n-k]\right)\right)
21+
.. math:: y[n]={\frac{1}{a_{0}}}
22+
\left(\left(b_{0}x[n]+b_{1}x[n-1]+b_{2}x[n-2]+...+b_{k}x[n-k]\right)-
23+
\left(a_{1}y[n-1]+a_{2}y[n-2]+...+a_{k}y[n-k]\right)\right)
2024
"""
2125

2226
def __init__(self, order: int) -> None:
@@ -34,17 +38,19 @@ def __init__(self, order: int) -> None:
3438

3539
def set_coefficients(self, a_coeffs: list[float], b_coeffs: list[float]) -> None:
3640
"""
37-
Set the coefficients for the IIR filter. These should both be of size order + 1.
38-
a_0 may be left out, and it will use 1.0 as default value.
41+
Set the coefficients for the IIR filter.
42+
These should both be of size `order` + 1.
43+
:math:`a_0` may be left out, and it will use 1.0 as default value.
3944
4045
This method works well with scipy's filter design functions
41-
>>> # Make a 2nd-order 1000Hz butterworth lowpass filter
42-
>>> import scipy.signal
43-
>>> b_coeffs, a_coeffs = scipy.signal.butter(2, 1000,
44-
... btype='lowpass',
45-
... fs=48000)
46-
>>> filt = IIRFilter(2)
47-
>>> filt.set_coefficients(a_coeffs, b_coeffs)
46+
47+
>>> # Make a 2nd-order 1000Hz butterworth lowpass filter
48+
>>> import scipy.signal
49+
>>> b_coeffs, a_coeffs = scipy.signal.butter(2, 1000,
50+
... btype='lowpass',
51+
... fs=48000)
52+
>>> filt = IIRFilter(2)
53+
>>> filt.set_coefficients(a_coeffs, b_coeffs)
4854
"""
4955
if len(a_coeffs) < self.order:
5056
a_coeffs = [1.0, *a_coeffs]
@@ -68,7 +74,7 @@ def set_coefficients(self, a_coeffs: list[float], b_coeffs: list[float]) -> None
6874

6975
def process(self, sample: float) -> float:
7076
"""
71-
Calculate y[n]
77+
Calculate :math:`y[n]`
7278
7379
>>> filt = IIRFilter(2)
7480
>>> filt.process(0)

backtracking/all_combinations.py

+34
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
def combination_lists(n: int, k: int) -> list[list[int]]:
1414
"""
15+
Generates all possible combinations of k numbers out of 1 ... n using itertools.
16+
1517
>>> combination_lists(n=4, k=2)
1618
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
1719
"""
@@ -20,6 +22,8 @@ def combination_lists(n: int, k: int) -> list[list[int]]:
2022

2123
def generate_all_combinations(n: int, k: int) -> list[list[int]]:
2224
"""
25+
Generates all possible combinations of k numbers out of 1 ... n using backtracking.
26+
2327
>>> generate_all_combinations(n=4, k=2)
2428
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
2529
>>> generate_all_combinations(n=0, k=0)
@@ -34,6 +38,14 @@ def generate_all_combinations(n: int, k: int) -> list[list[int]]:
3438
ValueError: n must not be negative
3539
>>> generate_all_combinations(n=5, k=4)
3640
[[1, 2, 3, 4], [1, 2, 3, 5], [1, 2, 4, 5], [1, 3, 4, 5], [2, 3, 4, 5]]
41+
>>> generate_all_combinations(n=3, k=3)
42+
[[1, 2, 3]]
43+
>>> generate_all_combinations(n=3, k=1)
44+
[[1], [2], [3]]
45+
>>> generate_all_combinations(n=1, k=0)
46+
[[]]
47+
>>> generate_all_combinations(n=1, k=1)
48+
[[1]]
3749
>>> from itertools import combinations
3850
>>> all(generate_all_combinations(n, k) == combination_lists(n, k)
3951
... for n in range(1, 6) for k in range(1, 6))
@@ -56,6 +68,28 @@ def create_all_state(
5668
current_list: list[int],
5769
total_list: list[list[int]],
5870
) -> None:
71+
"""
72+
Helper function to recursively build all combinations.
73+
74+
>>> create_all_state(1, 4, 2, [], result := [])
75+
>>> result
76+
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
77+
>>> create_all_state(1, 3, 3, [], result := [])
78+
>>> result
79+
[[1, 2, 3]]
80+
>>> create_all_state(2, 2, 1, [1], result := [])
81+
>>> result
82+
[[1, 2]]
83+
>>> create_all_state(1, 0, 0, [], result := [])
84+
>>> result
85+
[[]]
86+
>>> create_all_state(1, 4, 0, [1, 2], result := [])
87+
>>> result
88+
[[1, 2]]
89+
>>> create_all_state(5, 4, 2, [1, 2], result := [])
90+
>>> result
91+
[]
92+
"""
5993
if level == 0:
6094
total_list.append(current_list[:])
6195
return

cellular_automata/conways_game_of_life.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,8 @@ def new_generation(cells: list[list[int]]) -> list[list[int]]:
5858
# 3. All other live cells die in the next generation.
5959
# Similarly, all other dead cells stay dead.
6060
alive = cells[i][j] == 1
61-
if (
62-
(alive and 2 <= neighbour_count <= 3)
63-
or not alive
64-
and neighbour_count == 3
61+
if (alive and 2 <= neighbour_count <= 3) or (
62+
not alive and neighbour_count == 3
6563
):
6664
next_generation_row.append(1)
6765
else:

0 commit comments

Comments
 (0)