I have a following code which is meant to solve Project Euler 34 (finding numbers which are equal to the sum of their digits’ factorials). In particular, find_sols(N) returns all solutions of digit length N.
import cp. find_sols(N) = solve_all(Num) => A :: 1..9, Rest = new_list(N - 1), Rest :: 0..9, Digits = [A|Rest], Facs = new_list(N), foreach ({D, F} in zip(Digits, Facs)) element0(D, [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880], F) end, Reducer = new_list(N), Reducer[1] #= A, foreach (I in 2..N) Reducer[I] #= Reducer[I-1] * 10 + Digits[I] end, Num #= Reducer[N], sum(Facs) #= Num. sol = [find_sols(3), find_sols(5)].Here sol() gives [[145], [40585]].
The problem is, if I replace the last line with [find_sols(3), find_sols(4), find_sols(5)] then the answer for 5 digits disappears and I get [[145], [], []]. Is this a bug or expected behavior?
I came up with a workaround that resets the constraints after solving a constraint problem:
table find_sols(N) = Ans => ... cache_and_fail(N) = Ans => _ = find_sols(N), fail; Ans = find_sols(N). main => println(sum(flatten([cache_and_fail(N) : N in 2..7]))).cache_and_fail caches the solution for given N the first time, then fails to rewind the constraint solving context, and then fetches the cached result.
Unfortunately it doesn't work with a plain set, so it may be hard to wrap this kind of operation into a higher-order function or predicate.
By the way, sum does not accept nested lists when the first element of the outermost list is [].