Reputation: 1520
I'm searching for the biggest number meeting some condition, out of the set of numbers that are the product of all three-digit numbers.
The straightforward way is this:
(apply max (filter
my-test?
(for [x (range 100 1000)
y (range x 1000)]
(* x y))))
But this involves calculating half of all 900*900 products. If I find, e.g., (* 380 455)
matches my my-test?
predicate, I don't need to search any products where either factor is less than 380. Of course, I will also want to search the list from the biggest to the smallest if I'm doing this.
In psuedo-Clojure, I want to say something like this:
(for [x (range 999 99 -1) :while (>= x P)
y (range x 99 -1) :while (>= y P)]
(* x y))
where P
is something I magically set to (min x y)
each time I find a match.
Is there a way to do this in Clojure?
(I realize I could search the numbers in a diagonal fashion, given this specific problem I've set up. However, I'm now trying to solve for the general case of figuring out how to tell the for-loop that some its branches need pruned.)
Upvotes: 2
Views: 150
Reputation: 1520
@omeil suggested a loop
/recur
process, and this works much better. for
loops just aren't built for this.
(loop [x 999 y 999 min 99 candidates []]
(cond (<= x min) candidates ; exit condition
(<= y min) (recur (dec x) 999 min candidates) ; step x
(my-test? (* x y)) (recur x (dec y) (max min y) (conj candidates (* x y)))
:else (recur x (dec y) min candidates) ; step y
))
Upvotes: 5
Reputation: 430554
A very ugly solution would be to use an atom
:
(let [P (atom 0)]
(for [x (range 999 99 -1) :while (>= x @P)
y (range x 99 -1) :while (>= y @P)]
(do
(reset! P (+ x y))
(* x y))))
One thing that I think will get in the way is that the for
loop doesn't really care what the "output" is, so I am unable to see how it would be able to get that information natively.
The "right" solution is probably a recursive one that allows you to pass in (a.k.a. update) your minimum as you know more.
Upvotes: 1