1

私はPrologが初めてで、自分でこれに対する答えを得ることができないようです.

私が欲しいのは、Prologがすべての要素ではなく、リスト内の数値を数えることです。たとえば、次のようになります。

getnumbers([1, 2, c, h, 4], X).

私に与えるべきです:

X=3

getnumbers([], 0).
getnumbers([_ | T], N) :- getnumbers(T, N1), N is N1+1.

私が持っているものですが、明らかにリスト内のすべての要素が得られます。「数だけを数える」をどこにどのように配置すればよいかわかりません。

4

6 に答える 6

2

いつものように、リスト (および SWI-Prolog) を操作するときは、そこにあるモジュール lambda.pl を使用できます: http://www.complang.tuwien.ac.at/ulrich/Prolog-inedit/lambda.pl

:- use_module(library(lambda)).

getnumbers(L, N) :-
    foldl(\X^Y^Z^(number(X)
             ->  Z is Y+1
             ;   Z = Y),
          L, 0, N).
于 2013-04-21T17:57:19.530 に答える
1

論理的に純粋な状態を維持するのは簡単です。メタ述語 tcount/3を具体化された型テスト述語number_t/2(の略number_truth/2) と組み合わせて使用​​します。

number_t(X,Truth) :- number(X), !, Truth = true.
number_t(X,Truth) :- nonvar(X), !, Truth = false.
number_t(X,true)  :- freeze(X,  number(X)).
number_t(X,false) :- freeze(X,\+number(X)).

OPが提案したクエリを実行しましょう:

?- tcount(number_t,[ 1 , 2 ,c,h, 4 ],N)。
N = 3. % が決定論的に成功する

これは単調であることに注意してください。変数バインディングを遅らせることは、常に論理的に健全です。検討:

?- tcount(number_t,[A,B,C,D,E],N), A=1 , B=2 , C=c, D=h, E=4 .
N = 3、A = 1、B = 2、C = c、D = h、E = 4 ; % は成功しますが、選択ポイントを残します
間違い。

最後に、次の非常に一般的なクエリの回答をいくつか見てみましょう。

?- tcount(number_t,[A,B,C],N).
N = 3, freeze(A,  number(A)), freeze(B,  number(B)), freeze(C,  number(C)) ;
N = 2, freeze(A,  number(A)), freeze(B,  number(B)), freeze(C,\+number(C)) ;
N = 2, freeze(A,  number(A)), freeze(B,\+number(B)), freeze(C,  number(C)) ;
N = 1, freeze(A,  number(A)), freeze(B,\+number(B)), freeze(C,\+number(C)) ;
N = 2, freeze(A,\+number(A)), freeze(B,  number(B)), freeze(C,  number(C)) ;
N = 1, freeze(A,\+number(A)), freeze(B,  number(B)), freeze(C,\+number(C)) ;
N = 1, freeze(A,\+number(A)), freeze(B,\+number(B)), freeze(C,  number(C)) ;
N = 0, freeze(A,\+number(A)), freeze(B,\+number(B)), freeze(C,\+number(C)).
于 2015-06-16T03:07:12.873 に答える
0

これは、Prolog の自然パターン マッチングと number/1 を使用し、追加の句 (以下の 3) を使用して、数値ではないケースを処理します。

% 1 - base recursion
getnumbers([], 0).

% 2 - will pass ONLY if H is a number
getnumbers([H | T], N) :- 
    number(H),
    getnumbers(T, N1), 
    N is N1+1.

% 3 - if got here, H CANNOT be a number, ignore head, N is unchanged, recurse tail  
getnumbers([_ | T], N) :- 
    getnumbers(T, N).
于 2013-04-22T13:32:59.663 に答える
0

この種の問題に関する一般的なプロローグ イディオムは、最初に一般消費用の述語を定義し、それによって「ワーカー」述語を呼び出すようにすることです。多くの場合、ある種のアキュムレータを使用します。あなたの問題では、公共の消費述語は次のようなものです。

count_numbers( Xs , N ) :-
  count_numbers_in_list( Xs , 0 , N ) .

count_numbers_in_list( [] , N , N ) .
count_numbers_in_list( [X|Xs] , T , N ) :-
  number(X) ,
  T1 is T+1 ,
  count_numbers_in_list( Xs , T1 , N )
  .

再帰ビットを構成して、末尾再帰でもあるようにする必要があります。つまり、再帰呼び出しは引数リスト内のデータだけに依存します。これにより、コンパイラは各呼び出しで既存のスタック フレームを再利用できるため、実質的に、述語は再帰的ではなく反復的になります。適切な末尾再帰述語は、無限長のリストを処理できます。そうでないものは、再帰ごとに新しいスタック フレームを割り当て、最終的にそのスタックを吹き飛ばします。上記count_numbers_in_list/3は末尾再帰です。これではありません:

getnumbers([H | T], N) :- 
  number(H),
  getnumbers(T, N1), 
  N is N1+1.
于 2013-04-22T21:25:09.457 に答える