1

リストの最小値を見つけようとしています (学習経験として、min.

私のアプローチは次のとおりです。

minimo([X], X).
minimo([X,Y|Tail], N):-
    (X > Y, minimo([Y,Tail], Y));
    (X <= Y, minimo([X,Tail], X)).

これにより、次のエラーが表示されます。

構文エラー: 演算子が必要です

だから私の質問は:

  • 構文エラーの原因は何ですか?
  • 実際に正しい値が返される場合は修正されたら自分で試してみますが、これは実際には正しいアプローチでしょうか?

前もって感謝します。

4

4 に答える 4

4

すでに投稿されている他のバージョンに加えて、if-then-else を使用せず、リレーションにわかりやすい名前を使用するバージョンも検討してください (リストをその最小値に関連付けます)。

list_min([L|Ls], Min) :- list_min(Ls, L, Min).

list_min([], Min, Min).
list_min([L|Ls], Min0, Min) :-
    Min1 is min(L, Min0),
    list_min(Ls, Min1, Min).

このようなパターンは(左から)フォールドと呼ばれ、 `foldl/4 を使用して同等に記述できます。

list_min([L|Ls], Min) :- foldl(min_, Ls, L, Min).

min_(A, B, Min) :- Min is min(A, B).

クエリの例:

?- list_min([1,0,2], Min).
Min = 0.

ただし、これは真の関係ではなく、低レベルの算術演算を使用しているため、すべての方向に使用できるわけではないことに注意してください。たとえば、逆方向に使用しようとすると、次のようになります。

?- list_min([X,Y], 3).
エラー: is/2 : 引数が十分にインスタンス化されていません

これを真のソリューションにするには、などの制約を使用します。たとえば、整数に対する解の場合:

:- use_module(library(clpfd)).

list_min([L|Ls], Min) :- foldl(min_, Ls, L, Min).

min_(A, B, Min) :- Min #= min(A, B).

これはすべての方向に機能します。

?- list_min([X,Y], 3).
X in 3..sup,
3#=min(Y, X),
Y in 3..sup.
于 2011-11-11T10:44:37.830 に答える
4

あなたのプログラムにはいくつかのバグがあります:

  1. Joe Lehmann が指摘したように、'<='/2. である必要があります'=<'/2

  2. 再帰的に呼び出すとminimo/2、リストが間違って作成されます。[Y,Tail]使用する代わりに[Y|Tail]。それ以外の場合は、リストを 2 番目の要素として持つリストを取得します。

  3. またはの再帰呼び出しの 2 番目の引数をバインドしminimo/2ます。代わりに、にバインドする必要があります。そうしないと、インスタンス化されません。YXNN

'->'カットを追加するか、if-then-else ( + ;)を使用して、プログラムをさらに改善できます。

minimo([X], X) :- !.
minimo([X,Y|Tail], N):-
    ( X > Y ->
        minimo([Y|Tail], N)
    ;
        minimo([X|Tail], N)
    ).
于 2011-11-08T07:13:20.473 に答える
3

構文エラーは、Prologの以下が= <であり、<=ではないためです。

このアプローチはうまくいくと思いますが、実際には避ける必要があります。節で。それを2つの句に分割するだけです。

また、再帰では[X、Tail]ではなく[X|Tail]のようなことをしたいと思います。

于 2011-11-08T05:47:02.210 に答える
2
min([H|T], Min) :- min(T, H, Min).

min([], Min, Min).
min([H|T], Min, Min1) :-
  (   H < Min
  ->  min(T, H, Min1)
  ;   min(T, Min, Min1) ).
于 2011-11-11T09:39:55.850 に答える