I know that there is already sample programs floating around that cover this, but I need to do the towers of hanoi with 6 discs a specific way for an assignment and I'm having trouble. Code I currently have is below:
s([],[],[]).
initial(s([1,2,3,4,5,6], [], [])).
goal(s([],[],[1,2,3,4,5,6])).
I also have 26 lines of code to verify valid states, however I tested that code on it's own and it works, the issue I'm having is creating the code to move the discs from stack to stack. An example of what I'm trying to do along with an example query is below:
changeState((s([A | B],[],[])), s([C], [D], [])) :- C is B, D is A.
?- changeState((s([1,2,3,4,5,6],[],[])), s([2,3,4,5,6], [1], [])).
So this would be the very beginning, where all 6 plates are on the first stack, and I want to move the top plate to the second stack. Essentially, I want to be able to remove the first element from a list, and add it to another list, whether it is empty or not.
Edits:
Got what I needed above working, now I just need help fixing the traverse predicate. Entire code is below:
%Post A, Post B, Post C
s([],[],[]).
initial(s([1,2,3,4,5,6], [], [])).
goal(s([],[],[1,2,3,4,5,6])).
valid([], _).
valid([H|_], X) :-
X < H.
changeState((s([A|T1], T2, T3)), s(T1, [A|T2], T3)) :-
valid(T2, A).
changeState((s([A|T1], T2, T3)), s(T1, T2, [A|T3])) :-
valid(T3, A).
changeState(s(T1, [A|T2], [B|T3]), s(T1, T2, [A,B|T3])) :-
valid(A,B).
changeState(s([A|T1], T2, [B|T3]), s([B,A|T1], T2, T3)) :-
valid(B, A).
changeState(s(T1, [A|T2], [B|T3]), s(T1, [B,A|T2], T3)) :-
valid(B, A).
changeState(s([A|T1], [B|T2], T3), s(T1, [A,B|T2], T3)) :-
valid(A,B).
changeState(s([A|T1], [B|T2], T3), s([B,A|T1], T2, T3)) :-
valid(B,A).
changeState(s([A|T1], T2, [B|T3]), s(T1, T2, [A,B|T3])) :-
valid(A,B).
changeState(s(T1, [A|T2], T3), s(T1, T2, [A|T3])) :-
valid(T3, A).
changeState(s(T1, [A|T2], T3), s([A|T1], T2, T3)) :-
valid(T1, A).
changeState(s(T1, T2, [A|T3]), s(T1, [A|T2], T3)) :-
valid(T2, A).
changeState(s(T1, T2, [A|T3]), s([A|T1], T2, T3)) :-
valid(T1, A).
traverse(StartNode,Sol,_) :- goal(StartNode), Sol = [StartNode].
traverse(StartNode,Sol,Visit) :- changeState(StartNode, NextNode),
not(member(NextNode, Visit)),
traverse(NextNode, PartialSol, [NextNode|Visit]),
Sol = [StartNode | PartialSol].
When I run this query:
?- traverse((s([1,2,3,4,5,6], [], [])), Sol, s([1,2,3,4,5,6], [], [])).
I get this output:
I've left it running after I get those responses for about 10 minutes and it still doesn't produce new ones so it's just continuing to run over and over again. As mentioned above, the point of the program is to solve the Towers of Hanoi problem with 6 discs using Lists. For those not familiar with Towers of Hanoi, you essentially need to move all discs from the first stack, to the last 3rd stack. You can only move 1 disc at a time, and you cannot place a larger disc on-top of a smaller disc. So you start with (s([1,2,3,4,5,6], [], [])) with each list representing Stack A, Stack B, Stack C respectively, and the goal is to end with (s([], [], [1,2,3,4,5,6])). I manually ran through an entire solution (63 moves) through the changeState predicates and all transitions were accepted, so the issue is with the transverse predicate. The transverse predicate is meant to show all steps that lead up to the solution, and all possible solutions. It's also meant to stop cycles, so that it's not just swapping the same 2 discs over and over again. Can't quite figure out what's wrong with my predicates thats causing me to get this output, I'm still fairly new to prolog, so I would appreciate any help!
You can use unification here instead of is/2 (which is typically used to evaluate expressions).
For example we can define a move from the first tower to the second tower, given the second tower is empty:
changeState((s([A|T1],[], T3)), s(T1, [A], T3)).
or we can move an element to the second tower that is non-empty, given the top of the stack is an element that is larger:
changeState(s([A|T1], [B|T2], T3), s(T1, [A,B|T2], T3)) :-
A < B.
The above will result in a total of 12 rules: 3 sources, times 2 destinations times 2 possibilities (empty destination, versus non-empty destination). This is not very elegant. We can construct a helper predicate that checks if the destination stack is valid, with:
valid_stack([], _).
valid_stack([H|_], X) :-
X < H.
so then we can compress the two rules above into:
changeState((s([A|T1], T2, T3)), s(T1, [A|T2], T3)) :-
valid_stack(T2, A).
This will thus result in six rules: three sources, and two destinations.
We thus no longer need to validate the moves, since if the changeState succeeds, then the proposed move is possible given the original state was valid.
This is not the full solution however (I leave the rest as an exercise). You will need a mechanism that enumerates over the possible moves, and makes sure that you do not end up in loops (like moving a disc constantly between two towers).
After using the traverse/3 predicate, we obtain a list of moves to the goal:
?- traverse(s([1,2,3,4,5,6], [], []), S, [s([1,2,3,4,5,6], [], [])]).
S = [s([1, 2, 3, 4, 5, 6], [], []), s([2, 3, 4, 5, 6], [1], []), s([3, 4, 5, 6], [1], [2]), s([1, 3, 4, 5|...], [], [2]), s([3, 4, 5|...], [], [1, 2]), s([4, 5|...], [3], [1, 2]), s([1|...], [3], [2]), s([...|...], [...|...], [...]), s(..., ..., ...)|...] [write]
S = [s([1, 2, 3, 4, 5, 6], [], []), s([2, 3, 4, 5, 6], [1], []), s([3, 4, 5, 6], [1], [2]), s([1, 3, 4, 5, 6], [], [2]), s([3, 4, 5, 6], [], [1, 2]), s([4, 5, 6], [3], [1, 2]), s([1, 4, 5, 6], [3], [2]), s([4, 5, 6], [1, 3], [2]), s([2, 4, 5, 6], [1, 3], []), s([1, 2, 4, 5, 6], [3], []), s([2, 4, 5, 6], [3], [1]), s([4, 5, 6], [2, 3], [1]), s([1, 4, 5, 6], [2, 3], []), s([4, 5, 6], [1, 2, 3], []), s([5, 6], [1, 2, 3], [4]), s([1, 5, 6], [2, 3], [4]), s([5, 6], [2, 3], [1, 4]), s([2, 5, 6], [3], [1, 4]), s([1, 2, 5, 6], [3], [4]), s([2, 5, 6], [1, 3], [4]), s([5, 6], [1, 3], [2, 4]), s([1, 5, 6], [3], [2, 4]), s([5, 6], [3], [1, 2, 4]), s([3, 5, 6], [], [1, 2, 4]), s([1, 3, 5, 6], [], [2, 4]), s([3, 5, 6], [1], [2, 4]), s([2, 3, 5, 6], [1], [4]), s([1, 2, 3, 5, 6], [], [4]), s([2, 3, 5, 6], [], [1, 4]), s([3, 5, 6], [2], [1, 4]), s([1, 3, 5, 6], [2], [4]), s([3, 5, 6], [1, 2], [4]), s([5, 6], [1, 2], [3, 4]), s([1, 5, 6], [2], [3, 4]), s([5, 6], [2], [1, 3, 4]), s([2, 5, 6], [], [1, 3, 4]), s([1, 2, 5, 6], [], [3, 4]), s([2, 5, 6], [1], [3, 4]), s([5, 6], [1], [2, 3, 4]), s([1, 5, 6], [], [2, 3, 4]), s([5, 6], [], [1, 2, 3, 4]), s([6], [5], [1, 2, 3, 4]), s([1, 6], [5], [2, 3, 4]), s([6], [1, 5], [2, 3, 4]), s([2, 6], [1, 5], [3, 4]), s([1, 2, 6], [5], [3, 4]), s([2, 6], [5], [1, 3, 4]), s([6], [2, 5], [1, 3, 4]), s([1, 6], [2, 5], [3, 4]), s([6], [1, 2, 5], [3, 4]), s([3, 6], [1, 2, 5], [4]), s([1, 3, 6], [2, 5], [4]), s([3, 6], [2, 5], [1, 4]), s([2, 3, 6], [5], [1, 4]), s([1, 2, 3, 6], [5], [4]), s([2, 3, 6], [1, 5], [4]), s([3, 6], [1, 5], [2, 4]), s([1, 3, 6], [5], [2, 4]), s([3, 6], [5], [1, 2, 4]), s([6], [3, 5], [1, 2, 4]), s([1, 6], [3, 5], [2, 4]), s([6], [1, 3, 5], [2, 4]), s([2, 6], [1, 3, 5], [4]), s([1, 2, 6], [3, 5], [4]), s([2, 6], [3, 5], [1, 4]), s([6], [2, 3, 5], [1, 4]), s([1, 6], [2, 3, 5], [4]), s([6], [1, 2, 3, 5], [4]), s([4, 6], [1, 2, 3, 5], []), s([1, 4, 6], [2, 3, 5], []), s([4, 6], [2, 3, 5], [1]), s([2, 4, 6], [3, 5], [1]), s([1, 2, 4, 6], [3, 5], []), s([2, 4, 6], [1, 3, 5], []), s([4, 6], [1, 3, 5], [2]), s([1, 4, 6], [3, 5], [2]), s([4, 6], [3, 5], [1, 2]), s([3, 4, 6], [5], [1, 2]), s([1, 3, 4, 6], [5], [2]), s([3, 4, 6], [1, 5], [2]), s([2, 3, 4, 6], [1, 5], []), s([1, 2, 3, 4, 6], [5], []), s([2, 3, 4, 6], [5], [1]), s([3, 4, 6], [2, 5], [1]), s([1, 3, 4, 6], [2, 5], []), s([3, 4, 6], [1, 2, 5], []), s([4, 6], [1, 2, 5], [3]), s([1, 4, 6], [2, 5], [3]), s([4, 6], [2, 5], [1, 3]), s([2, 4, 6], [5], [1, 3]), s([1, 2, 4, 6], [5], [3]), s([2, 4, 6], [1, 5], [3]), s([4, 6], [1, 5], [2, 3]), s([1, 4, 6], [5], [2, 3]), s([4, 6], [5], [1, 2, 3]), s([6], [4, 5], [1, 2, 3]), s([1, 6], [4, 5], [2, 3]), s([6], [1, 4, 5], [2, 3]), s([2, 6], [1, 4, 5], [3]), s([1, 2, 6], [4, 5], [3]), s([2, 6], [4, 5], [1, 3]), s([6], [2, 4, 5], [1, 3]), s([1, 6], [2, 4, 5], [3]), s([6], [1, 2, 4, 5], [3]), s([3, 6], [1, 2, 4, 5], []), s([1, 3, 6], [2, 4, 5], []), s([3, 6], [2, 4, 5], [1]), s([2, 3, 6], [4, 5], [1]), s([1, 2, 3, 6], [4, 5], []), s([2, 3, 6], [1, 4, 5], []), s([3, 6], [1, 4, 5], [2]), s([1, 3, 6], [4, 5], [2]), s([3, 6], [4, 5], [1, 2]), s([6], [3, 4, 5], [1, 2]), s([1, 6], [3, 4, 5], [2]), s([6], [1, 3, 4, 5], [2]), s([2, 6], [1, 3, 4, 5], []), s([1, 2, 6], [3, 4, 5], []), s([2, 6], [3, 4, 5], [1]), s([6], [2, 3, 4, 5], [1]), s([1, 6], [2, 3, 4, 5], []), s([6], [1, 2, 3, 4, 5], []), s([], [1, 2, 3, 4, 5], [6]), s([1], [2, 3, 4, 5], [6]), s([], [2, 3, 4, 5], [1, 6]), s([2], [3, 4, 5], [1, 6]), s([1, 2], [3, 4, 5], [6]), s([2], [1, 3, 4, 5], [6]), s([], [1, 3, 4, 5], [2, 6]), s([1], [3, 4, 5], [2, 6]), s([], [3, 4, 5], [1, 2, 6]), s([3], [4, 5], [1, 2, 6]), s([1, 3], [4, 5], [2, 6]), s([3], [1, 4, 5], [2, 6]), s([2, 3], [1, 4, 5], [6]), s([1, 2, 3], [4, 5], [6]), s([2, 3], [4, 5], [1, 6]), s([3], [2, 4, 5], [1, 6]), s([1, 3], [2, 4, 5], [6]), s([3], [1, 2, 4, 5], [6]), s([], [1, 2, 4, 5], [3, 6]), s([1], [2, 4, 5], [3, 6]), s([], [2, 4, 5], [1, 3, 6]), s([2], [4, 5], [1, 3, 6]), s([1, 2], [4, 5], [3, 6]), s([2], [1, 4, 5], [3, 6]), s([], [1, 4, 5], [2, 3, 6]), s([1], [4, 5], [2, 3, 6]), s([], [4, 5], [1, 2, 3, 6]), s([4], [5], [1, 2, 3, 6]), s([1, 4], [5], [2, 3, 6]), s([4], [1, 5], [2, 3, 6]), s([2, 4], [1, 5], [3, 6]), s([1, 2, 4], [5], [3, 6]), s([2, 4], [5], [1, 3, 6]), s([4], [2, 5], [1, 3, 6]), s([1, 4], [2, 5], [3, 6]), s([4], [1, 2, 5], [3, 6]), s([3, 4], [1, 2, 5], [6]), s([1, 3, 4], [2, 5], [6]), s([3, 4], [2, 5], [1, 6]), s([2, 3, 4], [5], [1, 6]), s([1, 2, 3, 4], [5], [6]), s([2, 3, 4], [1, 5], [6]), s([3, 4], [1, 5], [2, 6]), s([1, 3, 4], [5], [2, 6]), s([3, 4], [5], [1, 2, 6]), s([4], [3, 5], [1, 2, 6]), s([1, 4], [3, 5], [2, 6]), s([4], [1, 3, 5], [2, 6]), s([2, 4], [1, 3, 5], [6]), s([1, 2, 4], [3, 5], [6]), s([2, 4], [3, 5], [1, 6]), s([4], [2, 3, 5], [1, 6]), s([1, 4], [2, 3, 5], [6]), s([4], [1, 2, 3, 5], [6]), s([], [1, 2, 3, 5], [4, 6]), s([1], [2, 3, 5], [4, 6]), s([], [2, 3, 5], [1, 4, 6]), s([2], [3, 5], [1, 4, 6]), s([1, 2], [3, 5], [4, 6]), s([2], [1, 3, 5], [4, 6]), s([], [1, 3, 5], [2, 4, 6]), s([1], [3, 5], [2, 4, 6]), s([], [3, 5], [1, 2, 4, 6]), s([3], [5], [1, 2, 4, 6]), s([1, 3], [5], [2, 4, 6]), s([3], [1, 5], [2, 4, 6]), s([2, 3], [1, 5], [4, 6]), s([1, 2, 3], [5], [4, 6]), s([2, 3], [5], [1, 4, 6]), s([3], [2, 5], [1, 4, 6]), s([1, 3], [2, 5], [4, 6]), s([3], [1, 2, 5], [4, 6]), s([], [1, 2, 5], [3, 4, 6]), s([1], [2, 5], [3, 4, 6]), s([], [2, 5], [1, 3, 4, 6]), s([2], [5], [1, 3, 4, 6]), s([1, 2], [5], [3, 4, 6]), s([2], [1, 5], [3, 4, 6]), s([], [1, 5], [2, 3, 4, 6]), s([1], [5], [2, 3, 4, 6]), s([], [5], [1, 2, 3, 4, 6]), s([5], [], [1, 2, 3, 4, 6]), s([1, 5], [], [2, 3, 4, 6]), s([5], [1], [2, 3, 4, 6]), s([2, 5], [1], [3, 4, 6]), s([1, 2, 5], [], [3, 4, 6]), s([2, 5], [], [1, 3, 4, 6]), s([5], [2], [1, 3, 4, 6]), s([1, 5], [2], [3, 4, 6]), s([5], [1, 2], [3, 4, 6]), s([3, 5], [1, 2], [4, 6]), s([1, 3, 5], [2], [4, 6]), s([3, 5], [2], [1, 4, 6]), s([2, 3, 5], [], [1, 4, 6]), s([1, 2, 3, 5], [], [4, 6]), s([2, 3, 5], [1], [4, 6]), s([3, 5], [1], [2, 4, 6]), s([1, 3, 5], [], [2, 4, 6]), s([3, 5], [], [1, 2, 4, 6]), s([5], [3], [1, 2, 4, 6]), s([1, 5], [3], [2, 4, 6]), s([5], [1, 3], [2, 4, 6]), s([2, 5], [1, 3], [4, 6]), s([1, 2, 5], [3], [4, 6]), s([2, 5], [3], [1, 4, 6]), s([5], [2, 3], [1, 4, 6]), s([1, 5], [2, 3], [4, 6]), s([5], [1, 2, 3], [4, 6]), s([4, 5], [1, 2, 3], [6]), s([1, 4, 5], [2, 3], [6]), s([4, 5], [2, 3], [1, 6]), s([2, 4, 5], [3], [1, 6]), s([1, 2, 4, 5], [3], [6]), s([2, 4, 5], [1, 3], [6]), s([4, 5], [1, 3], [2, 6]), s([1, 4, 5], [3], [2, 6]), s([4, 5], [3], [1, 2, 6]), s([3, 4, 5], [], [1, 2, 6]), s([1, 3, 4, 5], [], [2, 6]), s([3, 4, 5], [1], [2, 6]), s([2, 3, 4, 5], [1], [6]), s([1, 2, 3, 4, 5], [], [6]), s([2, 3, 4, 5], [], [1, 6]), s([3, 4, 5], [2], [1, 6]), s([1, 3, 4, 5], [2], [6]), s([3, 4, 5], [1, 2], [6]), s([4, 5], [1, 2], [3, 6]), s([1, 4, 5], [2], [3, 6]), s([4, 5], [2], [1, 3, 6]), s([2, 4, 5], [], [1, 3, 6]), s([1, 2, 4, 5], [], [3, 6]), s([2, 4, 5], [1], [3, 6]), s([4, 5], [1], [2, 3, 6]), s([1, 4, 5], [], [2, 3, 6]), s([4, 5], [], [1, 2, 3, 6]), s([5], [4], [1, 2, 3, 6]), s([1, 5], [4], [2, 3, 6]), s([5], [1, 4], [2, 3, 6]), s([2, 5], [1, 4], [3, 6]), s([1, 2, 5], [4], [3, 6]), s([2, 5], [4], [1, 3, 6]), s([5], [2, 4], [1, 3, 6]), s([1, 5], [2, 4], [3, 6]), s([5], [1, 2, 4], [3, 6]), s([3, 5], [1, 2, 4], [6]), s([1, 3, 5], [2, 4], [6]), s([3, 5], [2, 4], [1, 6]), s([2, 3, 5], [4], [1, 6]), s([1, 2, 3, 5], [4], [6]), s([2, 3, 5], [1, 4], [6]), s([3, 5], [1, 4], [2, 6]), s([1, 3, 5], [4], [2, 6]), s([3, 5], [4], [1, 2, 6]), s([5], [3, 4], [1, 2, 6]), s([1, 5], [3, 4], [2, 6]), s([5], [1, 3, 4], [2, 6]), s([2, 5], [1, 3, 4], [6]), s([1, 2, 5], [3, 4], [6]), s([2, 5], [3, 4], [1, 6]), s([5], [2, 3, 4], [1, 6]), s([1, 5], [2, 3, 4], [6]), s([5], [1, 2, 3, 4], [6]), s([], [1, 2, 3, 4], [5, 6]), s([1], [2, 3, 4], [5, 6]), s([], [2, 3, 4], [1, 5, 6]), s([2], [3, 4], [1, 5, 6]), s([1, 2], [3, 4], [5, 6]), s([2], [1, 3, 4], [5, 6]), s([], [1, 3, 4], [2, 5, 6]), s([1], [3, 4], [2, 5, 6]), s([], [3, 4], [1, 2, 5, 6]), s([3], [4], [1, 2, 5, 6]), s([1, 3], [4], [2, 5, 6]), s([3], [1, 4], [2, 5, 6]), s([2, 3], [1, 4], [5, 6]), s([1, 2, 3], [4], [5, 6]), s([2, 3], [4], [1, 5, 6]), s([3], [2, 4], [1, 5, 6]), s([1, 3], [2, 4], [5, 6]), s([3], [1, 2, 4], [5, 6]), s([], [1, 2, 4], [3, 5, 6]), s([1], [2, 4], [3, 5, 6]), s([], [2, 4], [1, 3, 5, 6]), s([2], [4], [1, 3, 5, 6]), s([1, 2], [4], [3, 5, 6]), s([2], [1, 4], [3, 5, 6]), s([], [1, 4], [2, 3, 5, 6]), s([1], [4], [2, 3, 5, 6]), s([], [4], [1, 2, 3, 5, 6]), s([4], [], [1, 2, 3, 5, 6]), s([1, 4], [], [2, 3, 5, 6]), s([4], [1], [2, 3, 5, 6]), s([2, 4], [1], [3, 5, 6]), s([1, 2, 4], [], [3, 5, 6]), s([2, 4], [], [1, 3, 5, 6]), s([4], [2], [1, 3, 5, 6]), s([1, 4], [2], [3, 5, 6]), s([4], [1, 2], [3, 5, 6]), s([3, 4], [1, 2], [5, 6]), s([1, 3, 4], [2], [5, 6]), s([3, 4], [2], [1, 5, 6]), s([2, 3, 4], [], [1, 5, 6]), s([1, 2, 3, 4], [], [5, 6]), s([2, 3, 4], [1], [5, 6]), s([3, 4], [1], [2, 5, 6]), s([1, 3, 4], [], [2, 5, 6]), s([3, 4], [], [1, 2, 5, 6]), s([4], [3], [1, 2, 5, 6]), s([1, 4], [3], [2, 5, 6]), s([4], [1, 3], [2, 5, 6]), s([2, 4], [1, 3], [5, 6]), s([1, 2, 4], [3], [5, 6]), s([2, 4], [3], [1, 5, 6]), s([4], [2, 3], [1, 5, 6]), s([1, 4], [2, 3], [5, 6]), s([4], [1, 2, 3], [5, 6]), s([], [1, 2, 3], [4, 5, 6]), s([1], [2, 3], [4, 5, 6]), s([], [2, 3], [1, 4, 5, 6]), s([2], [3], [1, 4, 5, 6]), s([1, 2], [3], [4, 5, 6]), s([2], [1, 3], [4, 5, 6]), s([], [1, 3], [2, 4, 5, 6]), s([1], [3], [2, 4, 5, 6]), s([], [3], [1, 2, 4, 5, 6]), s([3], [], [1, 2, 4, 5, 6]), s([1, 3], [], [2, 4, 5, 6]), s([3], [1], [2, 4, 5, 6]), s([2, 3], [1], [4, 5, 6]), s([1, 2, 3], [], [4, 5, 6]), s([2, 3], [], [1, 4, 5, 6]), s([3], [2], [1, 4, 5, 6]), s([1, 3], [2], [4, 5, 6]), s([3], [1, 2], [4, 5, 6]), s([], [1, 2], [3, 4, 5, 6]), s([1], [2], [3, 4, 5, 6]), s([], [2], [1, 3, 4, 5, 6]), s([2], [], [1, 3, 4, 5, 6]), s([1, 2], [], [3, 4, 5, 6]), s([2], [1], [3, 4, 5, 6]), s([], [1], [2, 3, 4, 5, 6]), s([1], [], [2, 3, 4, 5, 6]), s([], [], [1, 2, 3, 4, 5, 6])]
In SWI-Prolog, one needs to hit W you ask the interactive shell to print the full list.