clpz:monotonic.
digit(N) --> [D], { number_chars(N,[D]) }.
line(L) --> sequence(digit,"",L).
input(I) :- phrase_from_file(sequence(line,"\n",I),"i/03.in").
max(X,Y,Z) :- #Z #= max(#X,#Y).
jolt(0,_,0).
jolt(N,Xs,Jolt) :- #N_ #= #N - 1, length(OffLimits,N_), append(Useable,OffLimits,Xs),
foldl(max,Useable,0,Max), append(_,[Max|Rest],Xs), jolt(N_,Rest,Jolt_), #Jolt #= #Max * 10 ^ #N_ + #Jolt_.
part(N) --> maplist(jolt(N)), sum.
solve(P1,P2) :- input(I), part(2,I,P1), part(12,I,P2).
test :- make_test(day(3),solve,17158,170449335646486).
The easiest day so far! And I'm quite happy with how naturally my jolt function reads (find the max of the list that isn't off limits, then recurse on the rest which is everything after the max).
~/aoc25pl/03