HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Finding perimeters of right triangles with integer-length legs, up to a limit

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
perimeterstriangleswithlengthlimitfindinglegsintegerright

Problem

I have a nested for-loop that populates a list with elements:

a = []
for i in range(1, limit+1):
    for j in range(1, limit+1):
        p = i + j + (i**2 + j**2)**0.5
        if p <= limit:
            a.append(p)


I could refactor it into list comprehension:

a = [i + j + (i**2 + j**2)**0.5
     for i in range(1, limit+1)
     for j in range(1, limit+1)
     if i + j + (i**2 + j**2)**0.5 <= limit]


But now the same complex expression is in both parts of it, which is unacceptable. Is there any way to create a list in a functional way, but more elegantly?

I guess in Lisp I would use recursion with let. How it is done in more functional languages like Clojure, Scala, Haskell?

In Racket it's possible to bind expressions inside a for/list comprehension. I've found one solution to my problem:

[k
 for i in range(1, limit+1)
 for j in range(1, limit+1)
 for k in [i + j + (i**2 + j**2)**0.5]
 k <= limit]


I'm not sure how pythonic it is.

Solution

You can rewrite it with two separate comprehensions. One to generate the values and one to filter them out. You can use itertools.product to get the cartesian product.

a = [x for x in (i + j + (i**2 + j**2)**0.5
                 for i, j in itertools.product(range(1, limit+1), repeat=2))
     if x <= limit]

Code Snippets

a = [x for x in (i + j + (i**2 + j**2)**0.5
                 for i, j in itertools.product(range(1, limit+1), repeat=2))
     if x <= limit]

Context

StackExchange Code Review Q#19611, answer score: 3

Revisions (0)

No revisions yet.