Пролог - волчья козья капуста
Я работаю над игрой-головоломкой под названием "козлиная капуста-волк". Язык программирования - Пролог.
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:
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)
Вы получаете здесь избыточные ответы / решения. Устранить лишние ответы (прекращения) Goal
просто оберните эту цель setof(t, Goal, _).
Обратите внимание, что последний аргумент просто _
Вы также можете написать [t]
вместо.
? - длина (X, 7), setof (t, wgc ([w, w, w, w], X),_). X = [коза, ничего, капуста, коза, волк, ничего, коза]; X = [коза, ничего, волк, коза, капуста, ничего, коза].
Это работает до тех пор, пока ответы являются наземными.
Чтобы собрать решения в списке в явном виде, как предлагает @SergeyDymchenko, необходимо присвоить этому списку новое имя переменной и представить все решения в одном списке, что может оказаться более дорогостоящим, чем оставить это для реализации. В этом конкретном случае, однако, нет никакой внутренней разницы.