2012-03-14 9 views
4

私は 'the art of prolog'の本を読んでいて、 'ListOfIntegersの合計である場合に保持する関係の合計(ListOfIntegers、Sum)を定義する任意の補助述語 '.Iは、この解決策を思いついた:プロローグ内のリストの合計

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

これは私が望むように正確に動作しません。

私はXが

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

であることを期待していた

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

私はこの問題は、私が最初に「反復」に0に合計を「初期化」しなければならないということですが、それは残念ながら非常に手続きとなるだろうと思いました私はその仕事をするためにプロローグにはあまり適していません。 アイデアや提案はありますか?

答えて

3

問題をローカライズするための最良の方法は、最初のクエリを簡素化することです。

?- sum([0],S). 

true 
?- sum([],S). 

true 

でもそれらのために、あなたはどのSがそうすることを答えとして取得します。

?- 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; sum([X | Y]) - > X + sum(Y)である。そして、左右の宣言的読書はぼやけており、 ' - >'は論理的に混乱している。 –

+0

Prolog IIは ':-'の代わりに' - > 'を持っていました。これは1980年頃です。書き直しのアスペクトを強調することを意図していました。 Erlangは1987年頃です。 – false

4

あなたの最初の句はその変更に伴い

sum([], 0). 

、空虚なtrueリターンが消えるをお読みください、あなたは一つの問題が残っている:第三節は、加算の論理を反転させます。 sum/2に左引数でs/1項の数は、右引数でそれらの数と同じでなければなりませんので、それは

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

でなければなりません。

+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は "Prologの芸術"でPrologを学んでいますが、それでもなお優れた選択です。そして、最初に、s(X) - 自然数が使用されます。 – false

関連する問題