2

リスト内の変数の出現回数を数えるのに役立つ 3 年前の質問を見つけました。質問には以下の答えがありました。コードは機能します。しかし、どうすれば理解できませんか、誰かがこれを理解するのを手伝ってくれますか?

これが私が見つけたコードの答えです。引用符で書くことは答えの一部です:

count([],X,0). 
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count([X1|T],X,Z):- X1\=X,count(T,X,Z).

'ただし、2 番目の引数 X はインスタンス化されることになっていることに注意してください。たとえば、count([2,23,3,45,23,44,-20],23,C) は C を 2 に統一します。すべての要素のカウントが必要な場合は、'

:- use_module(library(lists)).

count([],X,0).
count([X|T],X,Y):- count(T,X,Z), Y is 1+Z.
count([X1|T],X,Z):- X1\=X,count(T,X,Z)

countall(List,X,C) :-
   sort(List,List1),
   member(X,List1),
   count(List,X,C).

「それならわかります」

 ?- countall([2,23,3,45,23,44,-20],X,Y).
   X = -20,
   Y = 1  ;
   X = 2,
   Y = 1 ;
   X = 3,
   Y = 1  ;
   X = 23,
   Y = 2  ;
   X = 44,
   Y = 1  ;
   X = 45,
   Y = 1  ;
   no

私は Prolog を初めて使用します。このコードの一部しか理解できません。

sort(List,List1),
member(X,List1),

この全体、特に Y がどのように印刷されているかについての説明をいただければ幸いです。

4

1 に答える 1

6

カウントについては、まずコードの意味を考えてみてください。

list_member_occ([], _, 0).       % list is empty, 0 occurrences
list_member_occ([X|Xs], X, N) :- % list has the element at the head
    list_member_occ(Xs, X, N0),  % count number of elements in the tail
    succ(N0, N).                 % the number of occurrences is the
                                 % next natural number
list_member_occ([Y|Xs], X, N) :-
    dif(X, Y),                   % head and the element are different
    list_member_occ(Xs, X, N).   % occurrences in the tail of the list
                                 % is the total number

このコードでは、succ(N0, N)は (ほぼ間違いなく) よりも " は "のN後の自然数です。理由の 1 つは、あらゆる方向で使用されることを意図していたことです。N0N is N0 + 1succ/2

?- succ(2, 3).
true.

?- succ(X, 4).
X = 3.

?- succ(1, X).
X = 2.

... whileは、バインドされていない左オペランドと共に使用する必要があります。このクエリを実行してくださいis/2

?- list_member_occ([1,1,2,1], X, 3).

...N自由変数ではなく数値である例。

述語の使用:

?- list_member_occ([1,2,1], X, N).
X = 1,
N = 2 ;
X = 2,
N = 1 ;
N = 0,
dif(X, 1),
dif(X, 2),
dif(X, 1).

dif/2とは対照的に、の興味深い特性の 1 つは、最後の解\=/2の変数に制約を課すことです。XX12

を使用してすべての回答を取得する理由については、次の点をdif/2考慮してください。

?- X = Y. % unify X and Y and succeed
X = Y.

?- X \= Y. % succeed if you cannot unify X and Y
false.

?- dif(X, Y). % succeed if X and Y are and will be different
dif(X, Y).

を使用するX \= Yと、Prolog はその引数を統合しようとし、統合が成功すると失敗します。これは、すべての自由変数が互いに統一された解しか得られず、自由変数が互いに異なる解を見逃すことを意味します。

についてはY = ...、トップ レベルでクエリを作成すると、このクエリの証明が成功したときに作成されたすべての新しい変数バインディングがレポートされます。最も簡単な例として:

両方を含めて、3 から 5 の間にある数は?

?- between(3, 5, X).
X = 3 ;
X = 4 ;
X = 5.

Xもちろん、 の値を手動で出力する必要はありません。次の回答を取得するには、セミコロンを入力するだけです。?-最後の回答の後、完全に停止してプロンプトに戻ります。

並べ替えについて: リスト全体を並べ替えますが、並べ替えられたリストの最初の 9 つの要素のみを表示します。SWI-Prolog のこの FAQ ページを参照してください。簡単に言えば、最も簡単な方法は; true、クエリの後に入力して、少なくとも 1 つの選択ポイントがあることを確認し、 と を使用wpて用語全体と一部のみの表示を切り替えることです。

?- string_chars("the quick brown fox jumps over the lazy dog", Cs), sort(Cs, S) ; true.
Cs = [t, h, e, ' ', q, u, i, c, k|...],
S = [' ', a, b, c, d, e, f, g, h|...] [write]
Cs = [t, h, e, ' ', q, u, i, c, k, ' ', b, r, o, w, n, ' ', f, o, x, ' ', j, u, m, p, s, ' ', o, v, e, r, ' ', t, h, e, ' ', l, a, z, y, ' ', d, o, g],
S = [' ', a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z] .

?- string_chars("the quick brown fox jumps over the lazy dog", Cs), sort(Cs, S) ; true.
Cs = [t, h, e, ' ', q, u, i, c, k, ' ', b, r, o, w, n, ' ', f, o, x, ' ', j, u, m, p, s, ' ', o, v, e, r, ' ', t, h, e, ' ', l, a, z, y, ' ', d, o, g],
S = [' ', a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z] [print]
Cs = [t, h, e, ' ', q, u, i, c, k|...],
S = [' ', a, b, c, d, e, f, g, h|...] .

お役に立てれば。

于 2016-01-12T08:41:15.603 に答える