2

プロローグのリストで数字を二乗するにはどうすればよいですか?

リストには、数値、アトム、およびリストを含めることができます。

例:[a,b,2,3,4,[3],[c,d,9]]で、答えは である必要があります[a,b,4,9,16,[3],[c,d,9]]。答えでわかるように、リスト内の値の浅い二乗にする必要があります。

2->4

3->9

4->16

今まで試したこと、

square([],X).
square([A|B],X):-number(A), A is A*A, square(B,X).

X には二乗値が含まれます。基本ケースは、空のリストが受信されたときです。head (A) が数値かどうかを確認してから、数値を 2 乗し、A を A * A に変更します。次に、残りの部分 B に対して 2 乗関数を呼び出します。

私が間違っているところを提案してください。

編集:次のように正解。バストロジストによる。詳細な説明については、彼のコメントをお読みください。

squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
    number(L),
    SqrdL is L * L,
    squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
    \+number(L),
    squared_members(Ls, SqrdLs).

squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
  ( number(L)
  ->  M is L * L, squared_members(Ls, Ms)  
  ;   M = L, squared_members(Ls, Ms)
  ).
4

1 に答える 1

3

1 つのリスト A と別のリスト B の間の関係を記述する述語を定義しています。B は A と同じ要素をすべて持つ必要がありますが、A の数値は B で 2 乗する必要があります。

あなたが間違っているところ:

  • あなたの基底条件 はsquare([],X)、A が空の場合、B は何でもあることを示しています (したがって、たとえば、次のようなものでさえsquare([], 15)真です)。しかし、2 番目の引数は最初の引数と同じ数のメンバーを持つリストでなければならないため、これは私たちが求めている意味を捉えていません。つまり、最初のリストが空の場合、2 番目のリストは空でなければなりません。
  • 再帰ルールでも同じ問題が発生します。繰り返しのたびに未定の変数が渡され、最初のリストと 2 番目のリストの間の関係について何も述べられていないからです。
  • このルールは、alist の最初の要素が数値の場合にのみ成功します。たとえば、最初の要素がa(あなたの例のように)ある場合number(a)は、falseになります。述語には追加のルールがないため、最初のリストのすべてのメンバーが数値でない限り、単純に false になります。
  • Prolog の変数は、それらが表示されるコンテキスト全体で常に同じ一貫した値を持つ必要があります。それらは算術式の変数のように機能します。式a + b - b = aは、aとbの任意の値に当てはまりますが、* abにそれぞれ 1 つの一貫した値が割り当てられている場合に限ります。形式の Prolog ステートメントでも同じことが言えます。あなたが書いたものはa = a * aと言っていますが、これは当てはまりません。<variable> is <expression>

*定義が言っていることは、おおまかに次のとおりです。リストBは、Aが空のリストであり、Bが何かである場合、またはAの最初の要素が数値であり、その数値が等しい場合、リストAの2乗バージョンですそれ自体が 2 乗され、B は A の残りの 2 乗バージョンです。

考えられる解決策の 1 つを次に示します。

squared_members([], []).
squared_members([L|Ls], [SqrdL|SqrdLs]) :-
    number(L),
    SqrdL is L * L,
    squared_members(Ls, SqrdLs).
squared_members([L|Ls], [L|SqrdLs]) :-
    \+number(L),
    squared_members(Ls, SqrdLs).

この定義は、変数を共有するか、変数間の関係のチェーンによって関連付けられた要素を含めることによって、2 つのリスト間に意味のある関係を確立できることに注意してください (つまり、SqrdL は L * L であるため、L に関連付けられます)。この定義には、あなたのものよりも 1 つ多くの節があり、これにより、数値ではないリストのメンバーを考慮することができます。それらは変更されずに 2 番目のリストに追加されます。

より明確な表現のために If-Then-Else 表記を使用する別の定義は、次のようになります。

squared_members([], []).
squared_members([L|Ls], [M|Ms]) :-
  ( number(L)
  ->  M is L * L, squared_members(Ls, Ms)  
  ;   M = L, squared_members(Ls, Ms)
  ).
于 2013-11-03T00:34:33.753 に答える