Skip to content

Commit 07ad0a4

Browse files
committed
replaced itertools.product() with recursive generator that early-exits / backtracks
1 parent 8dc5c8d commit 07ad0a4

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

pythagorean_tuples.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,27 @@ def _pythagorean_triples_BP(a: int, factors: Counter):
8484
return triples
8585

8686

87+
def _product_powers(powers_table: list, limit: int, product=1):
88+
if not powers_table:
89+
yield product
90+
return
91+
92+
powers, *rest = powers_table
93+
for power in powers:
94+
if product * power >= limit:
95+
break
96+
yield from _product_powers(rest, limit, product * power)
97+
98+
8799
def _pythagorean_triples_B(a: int, factors: Counter):
88-
# TODO: minimise the number of possible deltas (without `itertools.product()`)
89100
triples = set()
90101
factors_list = list(factors)
91102
ranges = [range(0, min(ceil(log(a, factor)), 2 * factors[factor] + 1)) for factor in factors_list]
92-
for powers in product(*ranges):
93-
if (d := prod(factors_list[i] ** power for i, power in enumerate(powers))) < a:
94-
triples.add(_TRIPLE(a, d))
103+
104+
powers_table = [[factor ** exponent for exponent in exponents]
105+
for factor, exponents in zip(factors_list, ranges)]
106+
for d in _product_powers(powers_table, a):
107+
triples.add(_TRIPLE(a, d))
95108
return triples
96109

97110

@@ -109,12 +122,13 @@ def _pythagorean_triples_CP(a: int, factors: Counter):
109122

110123

111124
def _pythagorean_triples_C(a: int, factors: Counter):
112-
# TODO: minimise the number of possibilities (without `itertools.product()`)
113125
triples = set()
114126
factors_list = list(factors)
115127
ranges = [range(0, min(ceil(log(a, factor)), 2 * factors[factor] + 1)) for factor in factors_list]
116128
ranges[0] = range(1, min(ceil(log(a, 2)), 2 * factors[2])) # concerns the factor 2
117-
for powers in product(*ranges):
118-
if (d := prod(factors_list[i] ** power for i, power in enumerate(powers))) < a:
119-
triples.add(_TRIPLE(a, d))
129+
130+
powers_table = [[factor ** exponent for exponent in exponents]
131+
for factor, exponents in zip(factors_list, ranges)]
132+
for d in _product_powers(powers_table, a):
133+
triples.add(_TRIPLE(a, d))
120134
return triples

0 commit comments

Comments
 (0)