As part of a programming languages course I teach, I have developed a Prolog program for solving the 1980’s puzzle “Spinout” (from “Binary Arts”). Here is my code for anybody who might be interested:
% Spinout Puzzle Solver
% Author: M. Q. Rieck
% Last updated: Spring 2020
% This is my solution to the Prolog progrmamming project
% I assigned in CS 135, at Drake U. in Spring 2020.
% A function to create a list on N ones (representing
% vertical knobs/dials on the puzzle)
initList(0,[]).
initList(N,[H|T]) :-
N > 0,
M is N-1,
H is 1,
initList(M,T).
% Display the configuration of knobs/dials corresponding
% to a list of zeros and ones (i.e. bits)
showConfig0([]).
showConfig0([H|T]) :-
showConfig0(T),
((H is 0, format(' -'));
(H is 1, format(' |'))).
showConfig(L) :-
format('Configuration: '),
showConfig0(L), nl, nl.
% Change one of the bits in a list of bits
changeBit([],_,[]).
changeBit([H|T],0,[H1|T]) :-
H1 is 1-H.
changeBit([H|T],N,[H|T1]) :-
N > 0,
M is N-1,
changeBit(T,M,T1).
% Turn a specified knob/dial, numbering the knobs from
% right to left, beginning with zero. Actually, alter the
% list of bits representing the configuration of knobs, by
% changing the bit in a specified position of the bit list.
turn(N,T,L,L1,StartCount,EndCount) :-
EndCount is StartCount+1,
(T is 0; T is 1),
write('Step '),
write(EndCount),
write(': Turn knob '),
write(N),
((T is 0, write(' horizontally.'));
(T is 1, write(' vertically.'))),
nl,
changeBit(L,N,L1),
showConfig(L1).
% Assume that the rightmost knobs/dials are vertical
% (so the corresponding initial bits in the list are ones),
% make allowable step-by-step changes so as to cause
% these knobs/dials to become horizontal (so the
% corresponding bits are all changed to zeros)
moveHor(0,StartList,StartList,StartCount,StartCount).
moveHor(1,StartList,EndList,StartCount,EndCount) :-
turn(0,0,StartList,EndList,StartCount,EndCount).
moveHor(N,StartList,EndList,StartCount,EndCount) :-
N > 1,
M is N-1,
P is N-2,
moveHor(P,StartList,L1,StartCount,Count1),
turn(M,0,L1,L2,Count1,Count2),
moveVer(P,L2,L3,Count2,Count3),
moveHor(M,L3,EndList,Count3,EndCount).
% Assume that the rightmost knobs/dials are horizontal
% (so the corresponding initial bits in the list are zeros),
% make allowable step-by-step changes so as to cause
% these knobs/dials to become vertical (so the
% corresponding bits are all changed to ones)
moveVer(0,StartList,StartList,StartCount,StartCount).
moveVer(1,StartList,EndList,StartCount,EndCount) :-
turn(0,1,StartList,EndList,StartCount,EndCount).
moveVer(N,StartList,EndList,StartCount,EndCount) :-
N > 1,
M is N-1,
P is N-2,
moveVer(M,StartList,L1,StartCount,Count1),
moveHor(P,L1,L2,Count1,Count2),
turn(M,1,L2,L3,Count2,Count3),
moveVer(P,L3,EndList,Count3,EndCount).
% Demonstrate the solution to the Spinout puzzle, using
% N knobs/dials. Do this by first creating and displaying
% the initial configuration of all vertical knobs/dials,
% and then invoking the functon moveHor to change them
% all to the horizonal position.
spinout(N) :- nl,
initList(N,List),
showConfig(List),
moveHor(N,List,_,0,_),
!.