Because your range()
sequences are fixed, you don't need to use nested for
loops. Instead, use a single loop over itertools.product()
:
from itertools import product
for ai, bi, ci in product(range(1, 100), repeat=3):
if ai + bi + ci == 25 and ai * ai == ci:
break
Next, remove one of the repeats and lower the range values; you can trivially calculate ci
from ai
and bi
, and ranging beyond 23 is pointless (as ci
will only be 1 or greater if ai + bi
is 24 or less):
for ai, bi in product(range(1, 23), repeat=2):
ci = 25 - ai - bi
if ai * ai == ci:
break
That ci
can be negative here doesn't matter, as ai * ai
will always be a positive number.
Note that the above equation has four solutions, so breaking out on the first may not be the correct answer. You can calculate all possible solutions for a given target value with:
def triplets(target):
return (
(ai, bi, target - ai - bi)
for ai, bi in product(range(1, target - 2), repeat=2)
if ai * ai == target - ai - bi
)
This returns a generator, so can be asked for a single solution at a time with next()
:
gen = triplets(25)
print(next(gen, None))
If your inner loop sequences are dependent on the value of a parent loop, and you can't simplify the loop (like the ci = 25 - ai - bi
assignment above), then you perhaps need to use nested loops. You can always break out of such structures with an exception you catch; even standard ValueError
would do, or create a custom exception:
class Break(Exception):
pass
try:
for ai in <some_sequence>:
for bi in range(<based on ai>):
if <condition>:
raise Break
except Break:
# nested set of loops has exited
or nest the loop in a function and use return
:
def nested_loops(<arguments>):
for ai in <some_sequence>:
for bi in range(<based on ai>):
if <condition>:
return ai, bi