2

私のプログラムでは、リストのリストを作成する必要があります。各サブリストには、XとYの2つの数値と、これら2つの数値の合計と積が含まれています。これまでのところ、私は次のものを持っています:

genList(95, X,[]):-!.
genList(N, X,[[X,Y,Sum,Product]|Xs]):-
    Y is N+1,
    Sum is X+Y,
    Sum<101,
    Product is X*Y,
    N1 is N+1,
    genList(N1, X,Xs).

これは、genList(5,5、Q)のテストケースでは問題なく機能します。ただし、どの開始番号でも機能させるのに問題があります。

目標は、sum <= 100の数値のすべてのペアを見つけることです。したがって、1つの開始値について上記を実行すると、Xはすべてのペア1 <X <Y(sum <= 100)を検出し、すべての数値2でそれを実行します。 -Nは、可能なペアの完全なリストを提供します。

興味のある人のために、私が取り組んでいる問題は、ここで説明されている合計/積の問題です(ページの2番目)

誰かがこれを手伝ってくれるなら、それは大いにありがたいです!

また、組み込みのプロローグ述語は使用できないため、findallを使用するのではなく、これを行う複雑な方法です。

この述語によって生成された出力の小さな抜粋は次のとおりです。

[[5,6,11,30]、[5,7,12,35]、[5,8,13,40]、[5,9,14,45]、[5,10,15,50] 、[5,11,16,55]、[5,12,17,60]、[5,13,​​18,65]、[5,14,19,70]、[5,15,20,75] 、[5,16,21,80]、[5,17,22,85]、[5,18,23,90]、[5,19,24,95]、[5,20,25,100]、[ 5,21,26,105]、[5,22,27,110]、..。

編集:

さて、編集した後、これが私のコードの最新バージョンです。

非常に近いと思いますが、まだまだ正しくないことがあります。

番号のペアを循環しますが、「;」を使用する必要があります すべての答えを表示するために、それは私が望んでいることではありません。さらに、すべての回答が尽きた後、falseを返します。私はそれを理解することができません。

また、途中で完全な答えが得られますが、最後のペアのセットだけが残るまで、毎回サブリストが削除されます。

例:genList(0,48,48、Q)。私に与える:

[[48,49,97,2352],[48,50,98,2400],[48,51,99,2448],[48,52,100,2496]]
[[48,49,97,2352],[48,50,98,2400],[48,51,99,2448],[48,52,100,2496],[49,50,99,2450],[49,51,100,2499]]
[[48,49,97,2352],[48,50,98,2400],[48,51,99,2448],[49,50,99,2450],[49,51,100,2499]]
[[48,49,97,2352],[48,50,98,2400],[49,50,99,2450],[49,51,100,2499]]
[[48,49,97,2352],[49,50,99,2450],[49,51,100,2499]]
[[49,50,99,2450],[49,51,100,2499]]
false.

ご覧のとおり、サブリストは毎回削除されますが、理由がわかりません。

4

2 に答える 2

1

あなたが問題に間違った方法で取り組んでいるような気がします。私はあなたの述語が何をしているのか本当に理解していないことを認めなければなりません。

目標は、sum<=100である数値のすべてのペアを見つけることです。

非負の整数の順序付けられていないペアを意味すると仮定すると、それは

between(0, 100, Sum),
between(0, Sum, X),
Y is Sum - X,
X =< Y.

次に、そのようなすべてのペアのセット(リストとして)をで作成できますfindall/3

CLP(fd)を使用してこれを行うこともできます。

use_module(library(clpfd)).
[X, Y, Sum] ins 0..100,
X #=< Y,
X + Y #= Sum,
label([X,Y,Sum]).
于 2012-04-09T13:31:36.163 に答える
1

ここでPrologバックトラッキングを利用できます。欲しいものを言ってください。たとえば、次のように言うことができます。

  • Xとの間1になりたい100
  • Yとの間1になりたいmin(100 - X, X)
  • それから私は彼らのペアが欲しい

validPair/1述語がどのようになるかを見てみましょう。

validPair(X-Y) :-
    between(1, 100, X),
    Limit is min(100 - X, X),
    between(1, Limit, Y).

あなたはそれを呼び出すことができます

?- validPair(X).

で結果を参照する;か、で一致するすべてのペアのリストを作成しfindall/3ます。

編集:再帰があっても、ステートメントを保持できます:

  • Xとの間1になりたい100
  • Yとの間1になりたいmin(100 - X, X)
  • それから私は彼らのペアが欲しい

したがって、それを行うためのアイデアは、ワーカー述語を設定することです。

validPair(Result) :-
    validPair(0, 0, Result).
validPair(X, Y, R) :-
    ...

次に、ベースケースを設定します。

validPair(101, _Y, []) :- !.

ワーカー述語では、いくつかの条件で作成したステートメントを実装します。

validPair(X, Y, [SomeStuff|R]) :-
    X =< 100,
    Limit is min(100 - X, X),
    Y =< Limit,
    !,
    % we can go on and increment Y once we're finished
    validPair(X, NextY, R).
validPair(X, Y, R) :-
    % if we come here that means that Y is finished growing and
    % we have to increment X
    NextX is X + 1,
    validPair(NextX, 0, R).
于 2012-04-09T13:33:56.137 に答える