Download
:- use_module(library(clpfd)).
% Langford's Number Problem (CSPLib prob024)
% Place two copies of each number 1..N in a 2N sequence such that
% the two k's are exactly k positions apart.
% Only solvable when N mod 4 = 0 or N mod 4 = 3.
% predefined partial sequence (use _ for unknowns)
puzzle(4, [_, 1, _, 1, _, _, _, _]).
% solve the predefined puzzle
% solve(-S)
solve(S) :-
puzzle(N, S), % N = largest number (sequence length 2N), S = the predefined sequence
langford(N, S).
% langford(+N, ?S)
langford(N, S) :-
Len is 2 * N, % sequence has 2N slots
length(S, Len), % S = [_,_,...,_] with Len placeholders
S ins 1..N, % every value in S must be between 1 and N
numlist(1, N, Ks), % Ks = [1, 2, ..., N]
constrain_all(Ks, S, Len, Positions),
all_distinct(Positions),
label(Positions).
% constrain_all(+Ks, ?S, +Len, -Positions)
% base case: no numbers left to place
constrain_all([], _, _, []).
constrain_all([K|Ks], S, Len, [P1,P2|Ps]) :-
P1 in 1..Len, % first position of K anywhere in the sequence
P2 #= P1 + K + 1, % second position is exactly K+1 slots after the first
P2 #=< Len, % second position must not exceed the sequence length
element(P1, S, K), % S[P1] = K
element(P2, S, K), % S[P2] = K
constrain_all(Ks, S, Len, Ps).