Python generator for "barely obtuse" triangles (Project Euler 224)
It seems like you want to find a solution for a²+b²=c²-1 with some added constraints, like a&lt;=b&lt;=c, a+b+c&lt;=n, etc. by trying all possible combinations of a, b, and c and testing whether they satisfy all your conditions at once. This is pretty wasteful.

Instead of itertools.product, you can use a generator expression with three regular for loops. This has several advantages:


you could move some of the if clauses up after the first or second loop, i.e. you don't have to run the other loops if those conditions already fail at this point, e.g.

 for x in ... if test(x) for y in ... if test(y) ...

you can use the values of your previous variables in the lower and upper bounds for the later variables (in your case this replaces most of your if conditions)
you can basically calculate the value for c from a and b without testing all possible values


This is how I'd do it:

gen = ((a, b, int(c))
       for a in range(2, v_max_n + 1, 2)
       for b in range(a, min(v_max + 1, n - a - a), 2) # use a for lower and upper bounds
       for c in [(a ** 2 + b ** 2 + 1)**0.5]           # just a single candidate for c
       if  c % 1 == 0)                                 # whole-numbered c found?


Note that the calculation of c using very_large_number**0.5 might be imprecise with float; using decimal might work, though. However, even with those optimizations, testing much fewer values than your original loop (on the order of O(n²) instead of O(n³)), it might not be feasible to find solution for large values of a, b and c.

Also note that I did not thoroughly test this for off-by-one errors, since performance was the main concern.

Another thing that you might try: Invert the loops for a and for b, i.e. instead of testing all b for each a, no matter how large the difference, test all a up to b first. This does not decrease the number of combinations to test, but it seems to yield much more valid combinations in the "smaller" number much faster. Like this (upper bound for b can probably be reduced):

       for b in range(2, v_max + 1, 2)
       for a in range(2, b+1, 2)