Reputation: 9031
I am learning Clojure, and I found the solution to find the right triangle problem in a Haskell book using list comprehension making the problem neatly solved:
Finding the Right Triangle
The lengths of the three sides are all integers.
The length of each side is less than or equal to 10.
The triangle’s perimeter (the sum of the side lengths) is equal to 24.
In Haskell:
ghci> let rightTriangles' = [ (a,b,c) | c <- [1..10], a <- [1..c], b <- [1..a],
a^2 + b^2 == c^2, a+b+c == 24]
ghci> rightTriangles'
[(6,8,10)]
Is there such an elegant list comprehension solution in Clojure?
Upvotes: 8
Views: 3044
Reputation: 91837
(for [c (range 1 11)
a (range 1 c)
b (range 1 a)
:when (and (= (+ a b c) 24)
(= (* c c) (+ (* a a) (* b b))))]
[a b c])
You can also improve performance a fair bit by inserting :let [c2 (* c c)]
in between the c
and a
bindings, and then use c2
in the :when
, to avoid squaring c
more often than necessary.
Clojure's for
is basically do-notation for the list monad, with :when
acting like guard
, and :let
acting like let
. There's :while
too, but I don't know what haskell thing that corresponds to.
Upvotes: 10
Reputation: 74334
Clojure has for
syntax:
(for [ c (range 1 (inc 10))
a (range 1 (inc c))
b (range 1 (inc a))
:when (== (+ (* a a) (* b b))
(* c c))
:when (== (+ a b c) 24) ]
[a b c])
Upvotes: 13