пролог: исправление нескольких ответов (используя вырезать?) - PullRequest
5 голосов
/ 18 декабря 2009

Я считаю количество экземпляров в списке ...

count(_,[],N,N).
count(Elem,[Elem|List],N,M) :- !, N1 is N+1, count(Elem,List,N1,M). 
count(Elem,[_|List],N,M) :- count(Elem,List,N,M). 

Итак, я написал это двумя способами в прологе, и первый работает (выше), но мне было любопытно узнать, почему второй не дает (или, скорее, даст мне несколько ответов - только первый из которых является правильным ) почему это?

большое спасибо

count(Z,X,R) :- count2(Z,X,R,0).
count2(W,[H|T],L,A):- (W == H), Lnew is A+1, count2(W,T,L,Lnew).
count2(W,[H|T],L,A):- count2(W,T,L,A).
count2(W,[],A,A).

Ответы [ 3 ]

2 голосов
/ 18 декабря 2009

Причина, по которой ваша вторая попытка дает несколько решений, заключается в том, что второе предложение count2 не препятствует тому, чтобы W и H принимали одинаковые значения. Таким образом, даже если первое предложение count2 успешно выполнено, оно может вернуться назад и успешно выполнить второе предложение.

Вы можете исправить это, используя сокращение, как говорит Винсент Рамдани, или, если вы предпочитаете избегать использования разреза, вы можете просто добавить явную проверку во втором предложении, чтобы предотвратить объединение W и H, например:

count(Z,X,R) :- count2(Z,X,R,0).
count2(W,[W|T],L,A):- Lnew is A+1, count2(W,T,L,Lnew).
count2(W,[H|T],L,A):- W \= H, count2(W,T,L,A).
count2(_,[],A,A).

Также обратите внимание, что в первом предложении count2 теперь используется неявное объединение. Вместо явной проверки. Это немного короче и легче читать по моему мнению. Если, конечно, не было причины, по которой вы использовали равенство, а не объединение.

0 голосов
/ 18 декабря 2009

понял!

вот решение, которое работает:

count(Z,X,R) :- count2(Z,X,R,0).
count2(W,[H|T],L,A):- (W == H), !, Lnew is A+1, count2(W,T,L,Lnew).
count2(W,[H|T],L,A):- count2(W,T,L,A).
count2(W,[],A,A).

Спасибо, Винсент - ты заставил меня вернуться к вырезке!

0 голосов
/ 18 декабря 2009

Ваш вопрос включает в себя ответ ... разрез. Срез всегда успешен и имеет побочный эффект «обрезки» деривационного дерева. Как правило, вы не можете отменить передачу.

Первый пример выполнит разрез, если цель объединяется со вторым правилом. В некотором смысле этот выбор становится фиксированным. Если после сбоя произошел сбой или произошел откат назад, то не произошло повторного отслеживания, исключая множественные ответы. Разрез полезен, когда ответы взаимоисключающие. То есть, когда вы найдете первый ответ, другие не будут иметь смысла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...