Skip to content

Instantly share code, notes, and snippets.

@iogakos
Created January 6, 2012 13:53
Show Gist options
  • Save iogakos/1570713 to your computer and use it in GitHub Desktop.
Save iogakos/1570713 to your computer and use it in GitHub Desktop.
%%
% Authors:
% - Ioannis Gakos, 3634
% - Alkis Livathinos, 3690
%%
% Place disk on a pole
%
:- dynamic disk_state/2.
% Retract all predicates first
%
:- retractall(disk_state(_,_)).
% Fixed initialization
%
:- forall(
member(X, [1, 2, 3, 4, 5]), assert(disk_state(X, 1))
).
% Use the following predicate to initialize the game
%
% N: disks
% P: pole to place the disks given
%
% Example: state_initialization([1,2,3,4,5], 3)
%
state_initialization(N, P) :-
forall(
member(X, N), assert(disk_state(X, P))
).
% Show in which state the game is by printing to std
% out, on which pole each disk has been placed
%
% OUT: D:1 on P:2, means disk 1 is placed on pole 2
%
show_state(N) :-
forall(
member(X, N), (
disk_state(X, Y),
write('D:'), write(X),
write(' on '),
write('P:'), write(Y),
nl
)
).
% The following minimum related predicates are used
% to find the minimum element of a list
%
minimum([Min], Min). % minimum found
minimum([H,K|T],M) :-
H =< K, % H is less than or equal to K
minimum([H|T],M). % so use H
minimum([H,K|T],M) :-
H > K, % H is greater than K
minimum([K|T],M). % so use K
% Check if legal move
legal_move(Disk, Dest) :-
is_ontop(Disk), % check if on top
smaller_than(Disk, Dest). % check if smaller disk exists
% Checks if the top disk on the destination pole
% is bigger than the one to be placed
%
smaller_than(Disk, Dest) :-
findall(X, (member(Pole, [Dest]), disk_state(X, Pole)), Disks),
minimum(Disks, Min) -> Disk<Min ; \+ fail.
% Checks if the disk to be moved is on top of the pole
%
is_ontop(Disk) :-
disk_state(Disk, S), % Find where the disk is located
findall(X, (member(Pole, [S]), disk_state(X, Pole)), Disks),
minimum(Disks, Min),
write(Min), write('-'), write(Disk), nl,
Min =:= Disk.
% Check if problem solved by evaluating all disk_state
% predicates
%
validate :-
forall(
member(X, [1,2,3,4,5]), disk_state(X, 3)
).
% Implement the move of a disk, by calling place predicate.
% For example, if you like to move disk 1, to pole 3,
% call place(1, 3)
%
place(Disk, Dest) :-
legal_move(Disk, Dest) -> write('Legal move'), nl,
disk_state(Disk, S), % Find where the disk is located
retract(disk_state(Disk, S)), % retract from previous state
assert(disk_state(Disk, Dest)), % store new state
show_state([1,2,3,4,5]),
(validate -> write('Problem solved'); write('Not yet solved'));
write('Illegal move'), fail.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment