Prologue - Goat Wolf Cabbage

I am working on a puzzle game called Goat Wolf Cabbage. The programming language is Prolog.

change(e,w). change(w,e). move([X,X,Goat,Cabbage],wolf,[Y,Y,Goat,Cabbage]) :- change(X,Y). move([X,Wolf,X,Cabbage],goat,[Y,Wolf,Y,Cabbage]) :- change(X,Y). move([X,Wolf,Goat,X],cabbage,[Y,Wolf,Goat,Y]) :- change(X,Y). move([X,Wolf,Goat,Cabbage],nothing,[Y,Wolf,Goat,Cabbage]) :- change(X,Y). oneeq(X,X,WW). oneeq(X,WWW,X). safe([Man,Wolf,Goat,Cabbage]) :- oneeq(Man,Goat,Wolf), oneeq(Man,Goat,Cabbage). wgc([e,e,e,e],[]). wgc(Config,[FirstMove|OtherMoves]) :- move(Config,FirstMove,NextConfig), safe(NextConfig), wgc(NextConfig,OtherMoves). 

To make it work, I call length(X,7),wgc([w,w,w,w],X). and he shows the result. The problem is that it shows the first result many times, and then the second result:

 X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, wolf, goat, cabbage, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; X = [goat, nothing, cabbage, goat, wolf, nothing, goat] ; false. 

How to show both results only once? I tried to add! wgc character:

 wgc(Config,[FirstMove|OtherMoves]) :- move(Config,FirstMove,NextConfig), safe(NextConfig), wgc(NextConfig,OtherMoves), !. 

... but it only shows the first result once. Any ideas how to fix this?

+6
source share
2 answers

You can use the setof predicate to get a list of unique solutions:

 setof(X, (length(X,7),wgc([w,w,w,w],X)), Sols). X = X Sols = [[goat, nothing, cabbage, goat, wolf, nothing, goat], [goat, nothing, wolf, goat, cabbage, nothing, goat]] Yes (0.00s cpu) 
+4
source

You get redundant answers / solutions. To eliminate redundant (final) Goal responses simply wrap this target with setof(t, Goal, _). Note that the last argument is just _ , you can also write [t] .

  ? - length (X, 7), setof (t, wgc ([w, w, w, w], X), _) .
 X = [goat, nothing, cabbage, goat, wolf, nothing, goat];
 X = [goat, nothing, wolf, goat, cabbage, nothing, goat].

This works as long as the answers are reasonable answers.

Collecting decisions in a list explicitly, as @SergeyDymchenko suggests, requires specifying a new variable name for this list and presenting all solutions in one list, which can be more expensive than refusing to implement. In this particular case, however, there is no inherent difference.

+6
source

All Articles