Failed constraint solving invocation seems to affect subsequent runs

22 views
Skip to first unread message

Woosuk Kwak (Bubbler)

unread,
May 27, 2026, 10:53:31 PMMay 27
to Picat

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?

Neng-Fa Zhou

unread,
Jun 6, 2026, 10:35:42 AMJun 6
to Picat

You normally don't want to call solve/solve_all multiple times during one execution path as constraints are accumulated. In your example, the constraints posted by find_sols(4) are unsatisfiable. When constraints posted by find_sols(5) are added, the constraints in the store are still unsatisfiable.

If you have one call to solve in each path, the problem will not occur. For example,

main ?=>
     writeln(find_sols(3)),
     fail.
main ?=>
     writeln(find_sols(4)),
     fail.
main =>
     writeln(find_sols(5)),
     fail.

Cheers,
NF

Woosuk Kwak (Bubbler)

unread,
Jun 7, 2026, 9:20:52 AMJun 7
to Picat

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 [].

Reply all
Reply to author
Forward
0 new messages