A Beautiful (But Slow) Solution to Project Euler Problem #9

This little list comprehension in Haskell will find the Pythagorean triple specified in Problem 9:

[ (a, b, c) | c <- [1..], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a + b + c == 1000 ] !! 0

This is equivalent to taking the first element of

\{ (a, b, c) \; | \; c \in \mathbb{N}, b \in [1, c] \cap \mathbb{N}, a \in [1, b] \cap \mathbb{N}, a^2 + b^2 = c^2, a + b + c = 1000 \}.

Notice how close to mathematical notation the Haskell code is. Now, this code is not very fast; it instructs the computer to build a list of every triple of naturals (a, b, c) such that the triple is a Pythagorean triple and the sum of each element of the triple is 1000, starting at (1, 1, 1), (2, 1, 1), (2, 2, 1), (2, 2, 2)….

Here’s the gist.

Update. To the commenters on Reddit: Perhaps I should have been more clear about my experience here. I had just begun to learn Haskell and, having solved this problem already with the use of Euclid’s formula, I saw in the Haskell tutorial I was reading that one could solve this problem with a simple list comprehension, which struck me as beautiful in the sense of its simplicity and similarity to the normal set comprehension definition of the problem. Indeed, a faster implementation with a list comprehension would be

head [ (a, b, c) | c <- [1..], b <- [1..c], let a = 1000 - b - c, a^2 + b^2 == c^2 ]

3 thoughts on “A Beautiful (But Slow) Solution to Project Euler Problem #9

  1. One simple optimization is to remove one of the guards and only range over two variables, using the information that was encoded in the guard to determine the third variable. E.g., [ (a, b, c) | c <- [1..], b <- [1..c], let a = 1000 – b – c, a^2 + b^2 == c^2] !! 0

    I realize this loses some of the beautiful symmetry with how you'd normally write it as a mathematical set comprehension :)

  2. By the way, the notation [1,x] normally means the subset of R of numbers y such that 1 <= y <= x. A more mathematically conventional way of writing your set would be to use:

    b \in [1,c] \cap \mathbb{N}

    instead of simply b \in [1,c]. (And similarly for a.)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s