If anyone is interested in a clpfd solution for day 3, I have managed to write the following as a combination of constraints + careful labeling:
Spoilers
:- use_module(library(dcg/basics)).
:- use_module(library(dcg/high_order)).
:- use_module(library(clpfd)).
bank([H | Bank]) -->
battery(H), sequence(battery, Bank), eol.
banks(Banks) -->
sequence(bank, Banks).
battery(Jolt) -->
digit(D), {number_chars(Jolt, [D])}.
main(N, Value) :-
phrase_from_file(banks(Banks), "input-3.txt"),
maplist(joltage(N), Banks, Pairs),
maplist(maplist(label_pair), Pairs),
maplist(concat, Pairs, Values),
sum_list(Values, Value).
joltage(N, Bank, Selected) :-
length(Bank, M),
numlist(1, M, Indices),
transpose([Bank, Indices], Tuples),
length(Batteries, N),
length(SelectedIndices, N),
chain(SelectedIndices, #<),
transpose([Batteries, SelectedIndices], Selected),
tuples_in(Selected, Tuples).
label_pair([V, I]) :-
labeling([max(V), ff], [V, I]).
concat(Pairs, Value) :-
length(Pairs, N),
numlist(1, N, L),
reverse(L, L1),
maplist([I, [V, _], R]>>(R is V*10^(I-1)), L1, Pairs, Values),
sum_list(Values, Value).
So basically, tuples_in to label pairs of [Value-Index] and enforce a chain on the list of selected indices.
It’s not as fast as I would like, 14 seconds for part 2. So if anyone has a good suggestion with better constraints or labeling strategy, please comment 