Пролог - волчья козья капуста

Я работаю над игрой-головоломкой под названием "козлиная капуста-волк". Язык программирования - Пролог.

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, необходимо присвоить этому списку новое имя переменной и представить все решения в одном списке, что может оказаться более дорогостоящим, чем оставить это для реализации. В этом конкретном случае, однако, нет никакой внутренней разницы.

Другие вопросы по тегам