2014-12-04 2 views
-1

저는 프롤로그를 처음 접했고 아직 언어 구문에 어려움을 겪고 있습니다. 나는리스트를 통해 보이는 펑터를 쓰려고 노력하고 있는데,리스트의 모든 숫자의 합인 머리와 꼬리는 그 안에있는 다른 것이되는 새로운리스트를 만든다.프롤로그 - 목록에있는 숫자의 합

예 : [1,2, a, 3, b, c, 4] = [10, a, b, c]

지금 당장은 코드가 매우 조잡하다는 것을 두려워하지만 누군가 올바른 방향으로 나를 가리킬 수 있다면 크게 감사하겠습니다.

sumOfNumbers([X], Z) :- 
    number(X), 
    Z is Z+X. 
sumOfNumbers([X], _) :- 
    not(number(X)). 
sumOfNumbers([X|Rest], Z) :- 
    number(X), 
    Z is Z+X, 
    sumOfNumbers(Rest, Z). 
sumOfNumbers([X|Rest], Z) :- 
    not(number(X)), 
    sumOfNumbers(Rest, Z). 

바라지 만 이것은 완전히 근원적이지 않습니다. 다시 한번 감사

나는이 방법을 걸릴 것
+2

Prolog에서 Z는 Z + X는 X = 0 인 경우에만 참일 수 있습니다. – CapelliC

답변

0

: 별도의 숫자와 문자의 두 목록, 숫자를 합계와 문자의 목록에 추가로 주어진 목록 :

% Sum of list of numbers 
% sum(+List, -Sum) 
sum([], 0). 
sum([H|T], S) :- 
    sum(T, S1), 
    S is H + S1. 

% Separate a list into two lists one of numbers and second of non-numbers 
% separate(+InputList, -Numbers, -Letters) 
separate([], [], []). 
separate([H|T], [H|N], L) :- 
    number(H), 
    separate(T, N, L). 
separate([H|T], N, [H|L]) :- 
    separate(T, N, L). 

% This is your function 
sumOfNumbers(L, [Sum | Letters]) :- 
    separate(L, Numbers, Letters), 
    sum(Numbers, Sum). 

이 가장 최적의 방법 아니다 , 그러나 그것은 논리적으로 직접적이고 명확합니다.

0

몇 가지 변수를 사용하고 있습니다. Prolog는 선언적 언어이므로 일단 변수가 설정되면 변수를 변경할 수 없습니다. CapeliiC이 지적한 것처럼 X = 0 인 경우 Z is Z + X 만 true입니다. 따라서 대부분의 술어에 대한 설명은 true if xxxx/y unifies with…으로 시작합니다.

목록 재귀의 기본 사례는 대부분 빈 목록 []이고 하나의 요소 목록 [X]이 아닙니다. 대부분의 경우 프로그램을 복잡하게 만들거나 악화 시키지만 역 추적 후에 솔루션을 추가합니다.

다음은 목록을 보면서 처리해야하는 경우입니다.

  1. 목록에 추가 → 숫자가 아닌 머리가 숫자 → 반환 이전 결과 더한 찾을 수

  2. 머리입니다 목록을 [0]

  3. 을 반환 → 비어 이전 결과의 번호 다음에 목록에 추가하십시오.

이렇게하면 항상 출력 목록의 첫 번째 요소로 숫자가 있는지 확인해야합니다. 술어는 sumOfNumbers(Input, Sum, Rest)으로 작성되어 더 좋을 것입니다. 첫 번째 요소가 또 다른 인수라는 사실에주의를 기울이지 마십시오. 그래서 여기

는 프로그램입니다 :

sumOfNumbers([],[0]). 
sumOfNumbers([X|R],[Z|A]):- 
    number(X),    % cut here 
    sumOfNumbers(R,[Y|A]), 
    Z is Y + X. 
sumOfNumbers([X|R],[Y,X|A]):- 
    \+ number(X),   % cut here 
    sumOfNumbers(R,[Y|A]). 

당신은 추가 할 수는 실패한 다시 실행을 방지하기 위해 확인 (녹색) 컷 운영자 후.

나는 개인적으로 검사의 두 가지 경우가 발생하면 -> 연산자를 사용하는 것을 선호와 구조가 유사하다 : 당신이 값에 변수를 바인딩 일단

sumOfNumbers2([],[0]). 
sumOfNumbers2([X|R],Out):- 
    sumOfNumbers2(R,[Y|A]), 
    (number(X)->    % read as if X is a number 
     Z is Y + X, 
     Out = [Z|A]; 
    Out =[Y, X|A]). 
0

프롤로그에서이, 그것은 가 중단 변수이되어야합니다. 즉, 목록을 재귀 적으로 호출 할 때 호출 스택에서 상태를 유지해야합니다.그래서 나는 이와 같은 문제에 접근하여 도우미 술어을 추가 파라메터와 함께 사용하여 상태를 유지합니다.

일반적으로 헬퍼는 상태를 유지하는 데 필요한 추가 값을 사용하여 "공용"조건 자와 동일한 펑터를 가질 수 있습니다. 이것은 당신에게 달려 개선인지 여부

sum_of_numbers([]  , T , L , [T|L]) . 
sum_of_numbers([X|Xs] , T , L , R ) :- 
    (number(X) -> 
    T1 is T+X , L1 = L 
    ; 
    T1 = T , L1 = [X|L] 
) , 
    sum_of_numbers(Xs,T1,L1,R) 
    . 

:

sum_of_numbers(Xs,Ys) :-  % to sum the numbers in a list, 
    sum_of_numbers(Xs,0,[],Ys) % we invoke the helper, seeding its two accumulators appropriately. 
    . 

sum_of_numbers([]  , T , L , [T|L]) . % when the source list isexhausted, unify the accumulators with the result 
sum_of_numbers([X|Xs] , T , L , R ) :- % otherwise, 
    number(X) ,        % - if X is numeric 
    T1 is T+X ,        % - increment the tally 
    sum_of_numbers(Xs,T1,L,R)     % - and recurse down 
    .           % 
sum_of_numbers([X|Xs] , T , L , R ) :- % otherwise, 
    \+ number(X) ,       % - if X is non-numeric 
    sum_of_numbers(Xs,T,[X|L],R)    % - add X to the list accumulator 
    .           % - and recurse down. 

당신은 또한 절 2와 3을 결합하여 부드러운 컷 (의미)를 사용할 수 있습니다 : 나는이 같은 접근 것 .

관련 문제