Jump Puzzle
% Form of board, x for full, o for vacant spaces. Starting is % [ [o], [x, x], [x, x, x], [x, x, x, x] ] % Legal jumps along a line. linjmp([x, x, o | T], [o, o, x | T]). linjmp([o, x, x | T], [x, o, o | T]). linjmp([H|T1], [H|T2]) :- linjmp(T1,T2). % Rotate the board rotate([ [A], [B, C], [D, E, F], [G, H, I, J], [K, L, M, N, O]], [ [K], [L, G], [M, H, D], [N, I, E, B], [O, J, F, C, A]]). % A jump on some line. horizjmp([A|T],[B|T]) :- linjmp(A,B). horizjmp([H|T1],[H|T2]) :- horizjmp(T1,T2). % One legal jump. jump(B,A) :- horizjmp(B,A). jump(B,A) :- rotate(B,BR), horizjmp(BR,BRJ), rotate(A,BRJ). jump(B,A) :- rotate(BR,B), horizjmp(BR,BRJ), rotate(BRJ,A). % Series of legal boards. series(From, To, [From, To]) :- jump(From, To). series(From, To, [From, By | Rest]) :- jump(From, By), series(By, To, [By | Rest]). % Print a series of boards. This puts one board per line and looks a lot % nicer than the jumble that appears when the system simply beltches out % a list of boards. The write_ln predicate is a built-in which always % succeeds (is always satisfied), but prints as a side-effect. Therefore % print_series(Z) will succeed with any list, and the members of the list % will be printed, one per line, as a side-effect of that success. print_series_r([]) :- write_ln('*******************************************************'). print_series_r([X|Y]) :- write_ln(X), print_series_r(Y). print_series(Z) :- write_ln('\n*******************************************************'), print_series_r(Z). % A solution. solution(L) :- series([[o], [x, x], [x, x, x], [x, x, x, x], [x, x, x, x, x]], [[x], [o, o], [o, o, o], [o, o, o, o], [o, o, o, o, o]], L). % Find a print the first solution. solve :- solution(X), print_series(X). % Find all the solutions. solveall :- solve, fail. % This finds each solution with stepping. solvestep(Z) :- Z = next, solution(X), print_series(X).