2012-03-14 2 views
4

'프롤로그 아트'를 읽었으며 '합계가 ListOfIntegers의 합계 인 경우 보유하고있는 관계 합계 (ListOfIntegers, Sum)를 정의하는 연습을 발견했습니다. 모든 보조 술어 '.이 솔루션을 내놓았다 :프롤로그에 목록의 합

sum([],Sum). 
sum([0|Xs], Sum):-sum(Xs, Sum). 
sum([s(X)|Xs], Sum):-sum([X|Xs],s(Sum)). 

정확히 원하는대로 작동하지 않습니다.

?- sum([s(s(0)),s(0),s(s(s(0)))],X). 
true ; 
false. 

가 나는 문제가 내가 처음 '반복'에서 0 합계를 '초기화'해야한다는 것입니다하지만 매우 절차가 될 불행히도 것이라고 생각 X가

s(s(s(s(s(s(0)))))) 

것으로 기대하고 있었다 나는 프롤로그에서 그 일을하기가 쉽지 않다. 아이디어 나 제안이 있으십니까?

답변

3

문제를 지역화하는 가장 좋은 방법은 먼저 쿼리를 단순화하는 것입니다. [] 이후

?- sum([],s(s(0))). 
yes 

은 당신의 사실에 의해 처리 될 수 마찬가지로 오류가 바로 그 사실 거짓말을해야합니다. 당신은 말했다 :

[]의 합이 단지 무엇을 의미
sum([], Sum). 

. 당신은 아마 또 다른 오류가 마지막 규칙에 숨 깁니다 0

의미 ... 첫 번째 오류를 수정 한 후, 우리는 여기에

?- sum([0],Sum). 
Sum = 0 
?- sum([s(0)],Sum). 
no 

를 얻을, 마지막 절은 책임이있다. 읽습니다 :

sum([s(X)|Xs], Sum):-sum([X|Xs],s(Sum)). 

재귀 규칙은 Prolog에서 읽기가 상대적으로 까다 롭습니다. 그들을 이해하는 가장 간단한 방법은 :-을보고이 화살표 ←해야 실현하는 것입니다 (따라서 오른쪽에서 왼쪽 화살표) 의미 :

제공, 오른쪽에있는 목표라는 것을 true
우리는 왼쪽에있는 것을 결론 지었다.

그래서 비공식적 인 글씨에 비해 화살표는 반대 방향을 가리킨다!

우리의 쿼리를 들어, 우리는 그래서이 규칙은 이제 오른쪽에서 왼쪽으로 읽는 0

sum([s(0)| [] ], Sum) :- sum([0| []],s(Sum)). 

[]XsX 대체 다음 인스턴스를 고려할 수 있습니다 다만, sum([0],s(Sum))는 사실이다 ... 그러나 sum([0],0) 만 보유하고 있지만 그 목표는 아닙니다. 따라서이 규칙은 적용되지 않습니다! 당신이 의도하는 것은 반대 오히려이었다 : 정말 것에 대해 부동의 모든 seemingle 외부 s(X) 구조와 논리를, 다음 아니에요

sum([s(X)|Xs], s(Sum)):-sum([X|Xs],Sum). 
+0

그런 식으로 내 문제를 해결할 수 있다고 생각한 적 없다 ... 고마워! – kaiseroskilo

+0

다른 언어에서 영감을 얻은 첫 번째 Prolog 질문이 아닙니다. Erlang이 최근 Prolog 프로그래머를 망쳤다 고 생각하거나 특정 규칙에 대한 생각을 반영합니다. Erlang에서는 Peano없이 할 수 있습니다 : sum ([]) -> 0; 합계 ([X | Y]) -> X + 합계 (Y). 그리고 좌우의 선언적 읽기가 흐려지고 '->'는 논리적으로 혼란 스럽습니다. –

+0

프롤로그 II는':-' 대신'- '를 사용했습니다. 이것은 1980 년경이었습니다. 의도는 다시 쓰기 측면을 강조하는 것이 었습니다. Erlang은 약 1987입니다. – false

4

첫 번째 절은 그 변화와

sum([], 0). 

의 공허한 true 반환 사라질을 읽어야하고 하나의 문제를 남겨 : 세 번째 절은 요약의 논리를 반전시킵니다. sum/2에 왼쪽 인자의 s/1 용어의 개수가 오른쪽 인자에 그 (것)들의 수와 동일해야하기 때문

sum([s(X)|Xs], s(Sum)) :- sum([X|Xs], Sum). 

해야한다. 당신은 어떤S 할 것이라는 응답으로 얻을, 심지어 사람들을 위해

?- sum([0],S). 

true 
?- sum([],S). 

true 

:

+0

우수! 도와 줘서 고마워! – kaiseroskilo

0

.

이렇게하는 것이 더 쉽고 간단하지 않습니까?

우선, 따라서 보통 영어로 용액을 정의

  • 빈리스트의 합이 0
  • 비어리스트의 합이리스트의 헤드를 가산된다 목록의 꼬리의 합계.
  • 그 정의에서

는 프롤로그 직접 다음과

sum([]  , 0) . % the sum of an empty list is 0. 
sum([X|Xs] , T) :- % the sum of an non-empty list is obtained by: 
    sum(Xs , T1) , % - first computing the sum of the tail 
    T is X + T1  % - and then, adding that the to head of the list 
    .     % Easy! 
+1

OP는 "The Art of Prolog"로 프롤로그를 배우고 있으며, 여전히 탁월한 선택입니다. 그리고 처음에는 s (X) - 자연수가 사용되었습니다. – false