リスト内の要素が数字ではない数を数える小さなプログラムを書いています。ここに私のコードがあります:
not_number([],0).
not_number([X|T],R):-
not(number(X)),
R1 is R+1,
not_number(T,R1).
not_number([_|Tail],Result):-
not_number(Tail,Result).
このようなコードを実行すると:
?- not_number([1,2,3,5], R).
私はR = 0になっています(あるはずです)
R = 0.
しかし、リストにキャラクターを入れた場合:
?- not_number([1,2,3,5,a], R).
その後、私はこのエラーを取得しています:
ERROR: not_number/2: Arguments are not sufficiently instantiated
Exception: (10) not_number([a], _G247) ?
誰かがコードの問題を説明できますか?私はプロローグが初めてです。
あなたの問題は、このような算術計算では:
AはB
右側(B)のすべてが既知である必要があります。変数はありません。
次のようなことができます:
not_number(X, Y) :- not_number(X, Y, 0).
not_number([], Y, Y).
not_number([H|T], Y, Z) :-
\+ (number(H)),
Z1 is Z+1,
not_number(T, Y, Z1).
not_number([H|T], Y, Z) :-
number(H),
not_number(T, Y, Z).
(このコードをテストし、動作します)。
ここで、3番目の引数はアキュムレーターです。非数がいくつあるかをカウントします。リストが空の場合、この3番目の引数は2番目の引数と統合され、適切な答えになります。
プロローグは、機会があれば、可能なすべてのルートを通過します。このようなことをする場合:
cat(adam).
cat(eve).
そして尋ねる:
?- cat(X).
X = adamとX = eveの両方の答えを得ることができます。これはコードにも適用されます。リストの先頭が数字でない場合でも、これを行うことができます。
not_number([_|Tail],Result):-
not_number(Tail,Result).
希望する答えは得られません。興味のないルートを遮断する必要があります。この場合、私は追加します
number(Head).
この要素が数値でない場合にのみ、カウンタを1増やすことなくリスト内の要素をスキップするようにします。
Prologが他の結果を見つけるように強制するには、「;」を押す必要があります。キーボードで(このadamとeveの例のように)。
このような問題の一般的な解決策は、constraintsを使用することです。
たとえば、 clpfd 制約のみを使用する場合、プログラムは期待どおりに機能します。 (is)/2
を(#=)/2
に置き換えるだけで、すべての方向で機能する整数演算を取得できます:
:- use_module(library(clpfd)).
not_number([],0).
not_number([X|T],R):-
\+ number(X),
R1 #= R+1,
not_number(T,R1).
not_number([_|Tail],Result):-
not_number(Tail,Result).
サンプルクエリとその結果:
?-not_number([1,2,3,5]、R)。 R = 0。
また、(\+)/1
の代わりにISO述語not/1
を使用するようにコードを変更したことにも注意してください。