Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Пролог: исправление нескольких ответов (используя cut?)

Автор вопроса: v_a_bhatiaОтветов: 3

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

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).

prolog

Ответы

Ответ 1 · рейтинг 2 · nedned

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

Ответ 2 · Vincent Ramdhanie

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

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

Ответ 3 · рейтинг -1 · v_a_bhatia

понятно!

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

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).

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

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы