1

2 つのリストの項目を合計し、結果を別のリストに表示するプロローグ プログラムを作成しようとしています。

例えば:

リスト1:

[1, 3, 4, 2]

リスト 2:

[5, 1, 3, 0]

結果:

[6, 4, 7, 2]

これまでのところ、私はこれを持っています:

list_sum([],[],[]).
list_sum([H1|T1],[H2|T2],L3):-list_sum(T1,T2,[X|L3]), X is H1+H2.

?-list_sum([1,2,3,4],[1,2,3,4],R),write(R).
4

6 に答える 6

4

SWI-Prolog を使用している場合は、maplist を使用でき、そこにモジュール lambda が見つかりました: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl :

:- use_module(library(lambda)).

list_sum(L1, L2, L3) :-
    maplist(\X^Y^Z^(Z is X + Y), L1, L2, L3).
于 2013-04-10T20:57:11.933 に答える
2

@gusbroが言ったこと。さらに、異なる長さのリストに対処するために、操作の順序を再編成し、いくつかの特別なケースを追加する必要があります。

list_sum( []     , []     , []     ) .
list_sum( []     , [Y|Ys] , [Z|Zs] ) :- Z is 0+Y , list_sum( [] , Ys , Zs ) .
list_sum( [X|Xs] , []     , [Z|Zs] ) :- Z is X+0 , list_sum( Xs , [] , Zs ) .
list_sum( [X|Xs] , [Y|Ys] , [Z|Zs] ) :- Z is X+Y , list_sum( Xs , Ys , Zs ) .

Z is X+Y上記の例では評価 ( ) を移動する必要があるため、再帰のZに評価されます。これにより、次の 2 つのことが達成されます。

  • まず、述語をtail-recursiveにします。これは、ソリューションが反復的であるため、スタック スペースを消費しないことを意味します。コードでは、再帰全体が完了するまで評価は実行されません。各中間合計はスタックに保持され、戻る途中で右から左に評価されます。これは、大きなリストでスタックを吹き飛ばすことを意味します。

  • 第二に、再帰する前に各結果を評価するということは、すぐに失敗することを意味します。結果と一致しない最初の合計は、操作全体に失敗します。あなたのソリューションはゆっくりと失敗します。最初の項目の合計が結果リストの最初の項目にならない 10,000,000 個の項目リストを考えてみましょう: 10,000,000 個の項目すべてをトラバースし、 — スタックを吹き飛ばさなかったと仮定して — 合計を右から左に評価し始めます。あなたの述語は、最後の評価まで失敗しません。

于 2013-04-10T18:33:38.527 に答える
1

あなたはほとんどそこにいます。問題は、合計の結果を再帰呼び出しではなく、2 番目の句の先頭に配置する必要があることです。

list_sum([H1|T1],[H2|T2],[X|L3]):-list_sum(T1,T2,L3), X is H1+H2.

あなたが書いたように、結果として「返される」 L3 はX、再帰呼び出しからヘッド ( ) を削除したリストであることに注意してください。逆Xに、結果のリストに要素 ( ) を追加することを意味していました。

于 2013-04-10T18:09:13.760 に答える
0

結果はリストでなければならないX is H1+H2ので、Xはリストではなく、リストの先頭を単一の変数と一致させるだけなので、言うことはできません。もlist_sum([],[],0)同じ理由で正しくありません。答えは次のようになります。

sum([],[],[]).
sum([H1| T1], [H2| T2], [ResH| ResT]) :- 
        sum(T1, T2, ResT),
        ResH is H1+H2.

ただし、独自のコードを実行すると、最初に X が H1+H2 と一致し、2 回目の再帰呼び出しで X に値があり、T1+T2 の先頭と一致しません。を出力しnoます。

于 2013-04-10T18:20:14.043 に答える
0
domains
list=integer*
predicates
add(list,list,list)
clauses
add([],[],[]).
add([V1X|X],[V1Y|Y],[V1Z|Z]):-add(X,Y,Z),V1Z=V1X+V1Y.
于 2015-04-16T11:36:32.173 に答える