Skip to content

Commit 153bbd0

Browse files
authored
Merge pull request #2768 from keon/codex/fix-repo-audit-findings
Fix correctness issues found in repository audit
2 parents ad45996 + b4394e8 commit 153bbd0

37 files changed

Lines changed: 261 additions & 101 deletions

‎.github/workflows/publish.yml‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ jobs:
88
build:
99
runs-on: ubuntu-latest
1010
steps:
11-
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
11+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
1212

1313
- name: Set up Python
14-
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
14+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
1515
with:
1616
python-version: "3.13"
1717

@@ -22,7 +22,7 @@ jobs:
2222
run: python -m build
2323

2424
- name: Upload build artifacts
25-
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4
25+
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5
2626
with:
2727
name: dist
2828
path: dist/
@@ -35,7 +35,7 @@ jobs:
3535
id-token: write
3636
steps:
3737
- name: Download build artifacts
38-
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
38+
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6
3939
with:
4040
name: dist
4141
path: dist/

‎.github/workflows/python-app.yml‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,17 @@ on:
99
jobs:
1010
test:
1111
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
1214
strategy:
1315
matrix:
1416
python-version: ["3.10", "3.11", "3.12", "3.13"]
1517

1618
steps:
17-
- uses: actions/checkout@v4
19+
- uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
1820

1921
- name: Set up Python ${{ matrix.python-version }}
20-
uses: actions/setup-python@v5
22+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
2123
with:
2224
python-version: ${{ matrix.python-version }}
2325

@@ -31,3 +33,6 @@ jobs:
3133

3234
- name: Test with pytest
3335
run: python -m pytest
36+
37+
- name: Test documentation examples
38+
run: python -m pytest --doctest-modules algorithms/

‎algorithms/backtracking/factor_combinations.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def get_factors(number: int) -> list[list[int]]:
2525
2626
Examples:
2727
>>> get_factors(12)
28-
[[2, 6], [2, 2, 3], [3, 4]]
28+
[[2, 6], [3, 4], [2, 2, 3]]
2929
"""
3030
todo: list[tuple[int, int, list[int]]] = [(number, 2, [])]
3131
combinations: list[list[int]] = []

‎algorithms/backtracking/minimax.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def minimax(
2525
*depth* is the current depth (start with log2(len(scores))).
2626
2727
>>> minimax(2, True, [3, 5, 2, 9])
28-
5
28+
3
2929
>>> minimax(3, True, [3, 5, 2, 9, 12, 5, 23, 23])
3030
12
3131
"""

‎algorithms/backtracking/subsets.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ def subsets(nums: list[int]) -> list[list[int]]:
2424
A list of all subsets.
2525
2626
Examples:
27-
>>> sorted(subsets([1, 2]), key=str)
28-
[[], [1], [1, 2], [2]]
27+
>>> sorted(subsets([1, 2]), key=lambda item: (len(item), item))
28+
[[], [1], [2], [1, 2]]
2929
"""
3030
result: list[list[int]] = []
3131
_backtrack(result, nums, [], 0)
@@ -61,8 +61,8 @@ def subsets_v2(nums: list[int]) -> list[list[int]]:
6161
A list of all subsets.
6262
6363
Examples:
64-
>>> sorted(subsets_v2([1, 2]), key=str)
65-
[[], [1], [1, 2], [2]]
64+
>>> sorted(subsets_v2([1, 2]), key=lambda item: (len(item), item))
65+
[[], [1], [2], [1, 2]]
6666
"""
6767
result: list[list[int]] = [[]]
6868
for number in sorted(nums):

‎algorithms/compression/elias.py‎

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from __future__ import annotations
1616

17+
from collections.abc import Callable
1718
from math import log
1819

1920

@@ -50,46 +51,47 @@ def _unary(x: int) -> str:
5051
x: A positive integer.
5152
5253
Returns:
53-
A unary-coded string (x-1 ones followed by a zero).
54+
A unary-coded string (x-1 zeros followed by a one).
5455
"""
55-
return (x - 1) * "1" + "0"
56+
return (x - 1) * "0" + "1"
5657

5758

5859
def _elias_generic(
59-
length_encoding: callable,
60+
length_encoding: Callable[[int], str],
6061
x: int,
6162
) -> str:
6263
"""Generic Elias encoding using a pluggable length-encoding function.
6364
6465
Args:
6566
length_encoding: A function to encode the length prefix.
66-
x: A non-negative integer to encode.
67+
x: A positive integer to encode.
6768
6869
Returns:
6970
The Elias-coded bit string.
7071
"""
71-
if x == 0:
72-
return "0"
72+
if x <= 0:
73+
raise ValueError("Elias coding is defined only for positive integers")
7374

7475
first_part = 1 + int(_log2(x))
7576
remainder = x - 2 ** int(_log2(x))
7677
bit_count = int(_log2(x))
78+
suffix = _binary(remainder, bit_count) if bit_count else ""
7779

78-
return length_encoding(first_part) + _binary(remainder, bit_count)
80+
return length_encoding(first_part) + suffix
7981

8082

8183
def elias_gamma(x: int) -> str:
8284
"""Encode a positive integer using Elias gamma coding.
8385
8486
Args:
85-
x: A non-negative integer.
87+
x: A positive integer.
8688
8789
Returns:
8890
The Elias gamma coded bit string.
8991
9092
Examples:
9193
>>> elias_gamma(1)
92-
'0'
94+
'1'
9395
>>> elias_gamma(5)
9496
'00101'
9597
"""
@@ -100,14 +102,14 @@ def elias_delta(x: int) -> str:
100102
"""Encode a positive integer using Elias delta coding.
101103
102104
Args:
103-
x: A non-negative integer.
105+
x: A positive integer.
104106
105107
Returns:
106108
The Elias delta coded bit string.
107109
108110
Examples:
109111
>>> elias_delta(1)
110-
'0'
112+
'1'
111113
>>> elias_delta(5)
112114
'01101'
113115
"""

‎algorithms/graph/find_all_cliques.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,4 @@ def _get_connected(vertex: str, old_set: set[str]) -> set[str]:
5151

5252
possibles = set(edges.keys())
5353
_expand_clique(possibles, set())
54-
return solutions
54+
return sorted(sorted(clique) for clique in solutions)

‎algorithms/graph/satisfiability.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def solve_sat(
148148
149149
Examples:
150150
>>> solve_sat([(('x', False), ('y', False)), (('x', True), ('y', True))])
151-
{'x': False, 'y': False}
151+
{'x': True, 'y': False}
152152
"""
153153
graph = _build_graph(formula)
154154
vertex_scc = _scc(graph)

‎algorithms/graph/sudoku_solver.py‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ def _possible_values(self) -> dict[tuple[int, int], list[str]]:
5555
val[(i, j)] = []
5656
for i, j in val:
5757
inval = (
58-
d.get(("r", i), []) + d.get(("c", j), []) + d.get((i / 3, j / 3), [])
58+
d.get(("r", i), [])
59+
+ d.get(("c", j), [])
60+
+ d.get((i // 3, j // 3), [])
5961
)
6062
val[(i, j)] = [n for n in a if n not in inval]
6163
return val
@@ -100,7 +102,7 @@ def _valid_one(
100102
if n in self.val[ind] and (
101103
ind[0] == i
102104
or ind[1] == j
103-
or (ind[0] / 3, ind[1] / 3) == (i / 3, j / 3)
105+
or (ind[0] // 3, ind[1] // 3) == (i // 3, j // 3)
104106
):
105107
update[ind] = n
106108
self.val[ind].remove(n)

‎algorithms/graph/transitive_closure_dfs.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ def _dfs_util(self, source: int, target: int) -> None:
4848
"""
4949
self.closure[source][target] = 1
5050

51-
for adjacent in self.graph[target]:
51+
for adjacent in self.graph.get(target, []):
5252
if self.closure[source][adjacent] == 0:
5353
self._dfs_util(source, adjacent)
5454

0 commit comments

Comments
 (0)