Download
% 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 (two copies of each number)
    length(S, Len), % S = [_,_,...,_] with Len placeholders
    numlist(1, N, Ks),  % Ks = [1, 2, ..., N]
    reverse(Ks, KsRev),  % reverse to [N, ..., 2, 1]: place larger numbers first to be more efficient
    place_all(KsRev, S, Len). % place each number into S

% place_all(+Ks, ?S, +Len)
% base case: all numbers placed
place_all([], _, _).
place_all([K|Ks], S, Len) :-
    place(K, S, Len),  % place K at two valid positions
    place_all(Ks, S, Len).

% place(+K, ?S, +Len)
% try positions I and J = I+K+1, assign K to both slots
place(K, S, Len) :-
    between(1, Len, I), % try each possible start position (backtracking)
    J is I + K + 1, % second position is K+1 slots after the first
    J =< Len, % second position must not exceed sequence length
    nth1(I, S, K), % S[I] = K (fails if slot is already taken)
    nth1(J, S, K). % S[J] = K (fails if slot is already taken)