I need to solve the Ship Puzzle problem with using Prolog. Here are the facts.
There are 5 ships.
- The Greek ship leaves at six and
The number of arguments to the term ship(...)
in the second line (after solution predicate) is wrong. It is:
middleShip(ship(_,_,_,_,'Black',_),Shipes),
while it should be:
middleShip(ship(_,_,_,'Black',_),Shipes),
I haven't checked if this works, but this is causing your solver to fail for sure.
You asked:
So how can I solve this?
The following is a general methodology, that always works for pure, monotonic Prolog programs like yours. Your actual problem is that a specific goal should succeed, but it fails. So you got an unexpected failure. To localize the responsible part of your program, we will now systematically generalize your program. Step by step. Until we have a tiny little program fragment. This technique is called sometimes program slicing and sometimes program modification.
First of all, add the following to your code:
:- op(950, fy, *).
*_.
:- initialization(solution(_Port, _Carrier)).
Now we will remove one goal after the other by adding a *
in front of it and then rerun your program. So be prepared that you will rerun your program for a couple of times. To load the program enter at the toplevel:
?- [shipes].
This works virtually everywhere, like in SICStus, GNU, SWI, YAP. You will get now a warning about a "failed directive" or similar. So - be happy - for you can now reproduce the problem with ease!
Start adding a *
at the last goal. You might try several at once.
To reload after modification you might reenter that goal, or
in SICStus, better state ensure_loaded(shipes).
This checks if the file has been modified and only reruns it if it has been reloaded
in SWI, enter make.
Finally, I got the following program fragment:
middleShip(A,(_,_,A,_,_)). solution(PortSaidShip, TeaCarrier) :- Shipes = (ship(_,_,_,_,_),ship(_,_,_,_,_),ship(_,_,_,_,_),ship(_,_,_,_,_),ship(_,_,_,_,_)), *exists(ship('Greek',6,'Coffee',_,_),Shipes), middleShip(ship(_,_,_,_,'Black',_),Shipes), *exists(ship('English',9,_,_,_),Shipes), *rightOf(ship(_,_,'Coffee',_,_),ship('French',_,_,'Blue',_),Shipes), *rightOf(ship(_,_,_,_,'Marseille'),ship(_,_,'Cocoa',_,_),Shipes), *exists(ship('Brazilian',_,_,_,'Manila'),Shipes), *nextTo(ship(_,_,_,'Green',_),ship(_,_,'Rice',_,_),Shipes), *exists(ship(_,5,_,_,'Genoa'),Shipes), *rightOf(ship('Spanish',7,_,_,_),ship(_,_,_,_,'Marseille'),Shipes), *exists(ship(_,_,_,'Red','Hamburg'),Shipes), *nextTo(ship(_,_,_,'White',_),ship(_,7,_,_,_),Shipes), *lastShip(ship(_,_,'Corn',_,_),Shipes), *exists(ship(_,8,_,'Black',_),Shipes), *nextTo(ship(_,_,'Corn',_,_),ship(_,_,'Rice',_,_),Shipes), *exists(ship(_,6,_,_,'Hamburg'),Shipes), *exists(ship(PortSaidShip,_,_,_,'Port Said'),Shipes), *exists(ship(TeaCarrier,_,'Tea',_,_),Shipes).
So you need to understand four lines of code to understand your problem!
As others have already indicated, the problem is that once you use ship/6
and in other situations ship/5
.
Another remark: In stead of (_,_,_,A,B)
better write [_,_,_,A,B]
which is the common list notation.