Repository navigation
feat(sieve): add p49 and test - #53
Conversation
PR Summary by QodoAdd Project Euler 49 prime-permutation solver (segmented sieve) and tests
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Code Review by Qodo
1. Wrong return annotation
|
| def prime_permutations(n: int, perms: int) -> str: | ||
| """ | ||
| n: number of digits in the prime permutations | ||
| end in odd | ||
| perms: number of permutations to consider | ||
| _ _ _ 1,3,5,7,9 | ||
| """ | ||
| all_primes = sieve_n_digit_primes(n) | ||
| table = defaultdict(list) | ||
| for prime in all_primes: | ||
| key = "".join(sorted(str(prime))) | ||
| table[key].append(prime) | ||
|
|
||
| res = [] | ||
| for key, nums in table.items(): | ||
| if len(nums) < perms: | ||
| continue | ||
| nums_set = set(nums) | ||
| for start in nums_set: | ||
| for next_num in nums_set: | ||
| if next_num <= start: | ||
| continue | ||
| diff = next_num-start | ||
| seq = [start] | ||
| curr = start | ||
| while curr in nums_set and len(seq) < perms: | ||
| curr += diff | ||
| if curr in nums_set: | ||
| seq.append(curr) | ||
| else: | ||
| break | ||
| if len(seq) == perms: | ||
| res.append("".join([str(v) for v in seq])) | ||
| return res |
There was a problem hiding this comment.
1. Wrong return annotation 🐞 Bug ≡ Correctness
prime_permutations() is annotated to return str but actually returns a list of concatenated strings, which breaks the function’s API contract for type checkers and callers relying on hints.
Agent Prompt
### Issue description
`prime_permutations()` is declared as returning `str` but returns `res` which is a list of strings. This makes the public API misleading and can break static analysis / IDE usage.
### Issue Context
Tests already treat the return value as an iterable of strings (`sorted(prime_permutations(...))`).
### Fix Focus Areas
- Algorithms/numerical_methods/euler/p49.py[65-98]
### Proposed fix
- Change the signature to return `list[str]` (or `Sequence[str]`), e.g.:
- `def prime_permutations(n: int, perms: int) -> list[str]:`
- Optionally update the docstring to reflect that a list is returned.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| def sieve_n_digit_primes(n: int): | ||
| if n < 1: | ||
| return [] | ||
|
|
There was a problem hiding this comment.
2. Silent invalid n accepted 🐞 Bug ☼ Reliability
sieve_n_digit_primes() returns an empty list for n < 1, unlike other Euler utilities in this repo that raise ValueError for invalid n, which can mask upstream bugs by silently producing no results.
Agent Prompt
### Issue description
`sieve_n_digit_primes()` currently returns `[]` when `n < 1`, which silently accepts invalid input and can hide errors.
### Issue Context
Other Euler helpers in this repo raise `ValueError` on `n < 1`, so callers likely expect consistent validation behavior.
### Fix Focus Areas
- Algorithms/numerical_methods/euler/p49.py[20-23]
### Proposed fix
- Replace the early return with a `ValueError`, e.g.:
```py
if n < 1:
raise ValueError("n must be at least 1")
```
- Keep the existing `n == 1` handling (setting `low = 2`).
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| def is_prime(n: int): | ||
| if n < 1: | ||
| raise ValueError("n must be at least 1") | ||
| elif n == 1: | ||
| return False | ||
| elif n == 2: | ||
| return True | ||
| elif n % 2 == 0: | ||
| return False | ||
| else: | ||
| for i in range(3, int(math.sqrt(n))+1): | ||
| if n % i == 0: | ||
| return False | ||
| return True |
There was a problem hiding this comment.
3. Inefficient is_prime helper 🐞 Bug ➹ Performance
The module-level is_prime() uses float sqrt plus a step-1 divisor loop, which is slower than needed and less robust than using integer sqrt with odd divisors; it’s also not used by this module’s main logic.
Agent Prompt
### Issue description
`is_prime()` computes `int(math.sqrt(n))` and tests every divisor from 3 upward with step 1. This is slower than necessary and relies on floating-point sqrt.
### Issue Context
Within this module, `prime_permutations()` uses `sieve_n_digit_primes()` for primality generation, so this helper is currently redundant unless intended for external callers.
### Fix Focus Areas
- Algorithms/numerical_methods/euler/p49.py[5-18]
### Proposed fix
- Prefer integer sqrt and only test odd divisors:
```py
limit = math.isqrt(n)
for i in range(3, limit + 1, 2):
...
```
- Consider removing `is_prime()` if it’s not part of the intended public API for this module.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| from Algorithms.numerical_methods.euler.p49 import prime_permutations | ||
|
|
||
| def test_sol(): | ||
| assert sorted(prime_permutations(n=4, perms=3)) == ['148748178147', '296962999629'] | ||
|
|
||
| def test_higher_n(): | ||
| assert sorted(prime_permutations(n=5,perms=4)) == ['83987889379388798837'] No newline at end of file |
There was a problem hiding this comment.
4. Missing trailing newline 🐞 Bug ⚙ Maintainability
tests/euler/p49_test.py is missing a trailing newline, which creates diff noise and can fail formatting checks in stricter environments.
Agent Prompt
### Issue description
The new test file ends without a trailing newline (`\ No newline at end of file`).
### Issue Context
This repo has previously accepted fixes for the same formatting issue.
### Fix Focus Areas
- tests/euler/p49_test.py[1-7]
### Proposed fix
- Add a newline character at the end of `tests/euler/p49_test.py`.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
No description provided.