Completing dizzystar's answer:
Most of your recursions can be recur
red: You can put recur
inside if
, and hence under and
and or
, macros which expand to if
forms. For example ...
(defn qextend-helper [n x partial-sol partial-sol-list]
(if (<= x n)
(if (qextends? partial-sol x)
(recur n (inc x) partial-sol (conj partial-sol-list (conj partial-sol x)))
(recur n (inc x) partial-sol partial-sol-list))
partial-sol-list)
)
But the recursive call in qextend
:
(vec (concat ( ...)
(qextend n (rest partial-sol-list))))
... can't be dealt with by recur
, since it is buried in function calls, to concat
and vec
.
You can solve this problem by returning a lazy sequence, so making the partial-sol-list
argument lazy:
- get rid of
vec
- return the sequence - and - replace
concat
withlazy-cat
.
The resulting function is
(defn qextend [n partial-sol-list]
(if (seq partial-sol-list)
(lazy-cat (qextend-helper n 1 (first partial-sol-list) [])
(qextend n (rest partial-sol-list)))
nil))
You also have to avoid count
ing (and hence realizing) the lazy sequence: so useseq
instead to test whether there is anything in partial-sol-list
.
It works!
=> (sol-count 11)
2680