Пролог - волк коза капуста
Я работаю над головоломкой под названием "Волк козий капуста". Язык программирования Пролог.
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).
чтобы заставить его работать, я называю length(X,7),wgc([w,w,w,w],X).
и он показывает результат. Проблема в том, что он показывает, сколько раз первый результат, а затем второй результат:
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.
как показать только один раз как результаты? Я пытался добавить ! символ ОГК:
wgc(Config,[FirstMove|OtherMoves]) :-
move(Config,FirstMove,NextConfig),
safe(NextConfig),
wgc(NextConfig,OtherMoves), !.
...но он показывает только первый результат один раз. Есть идеи, как это исправить?
2 ответов
можно использовать setof
предикат для получения списка уникальных решений:
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)
вы получаете здесь избыточные ответы / решения. Для устранения избыточных ответов a (завершение) Goal
просто оберните эту цель с setof(t, Goal, _).
обратите внимание, что последний аргумент-это просто _
, вы можете также написать .
?- 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].
это работает до тех пор, пока ответы на них массу ответов.
сбор решений в списке явно, как предлагает @SergeyDymchenko, требует дать новое имя переменной этому списку и представить все решения в одном списке, который может быть более дорогостоящим, чем оставить это на реализацию. В этом конкретном случае, однако, нет никакой внутренней разницы.