1

Prolog のテストが近づいていますが、その基本的な考え方がよくわかりません。私が経験してきた例のいくつかはある程度理解できますが、座って特定の問題を解決する方法をすぐに知ることはできません。

私たちの教授は私たちにいくつかの例を教えてくれました.

例は私たちの本から来ました:

Donna, Danny, David, and Doreen were seated at a table. 
The men sat across from each other, as did the women. 
They each ordered a different drink and main course.

Facts:

Doreen sat beside the person that ordered steak
The chicken came with a coke
The person with lasagna sat across from the person with milk
David never drinks coffee
Donna only drinks water
Danny could not afford to order steak

私は、各人に関連するリストがあり、事実を入力する方法を試しましたが、これは正しいアプローチではないと思います. 誰かが私にこれを説明してもらえますか? ありがとう!

編集:

これは私が最終的に得たコードです。パズルのほとんどを完成させ、前菜の1つと飲み物の1つを残しますが、それは修正可能なはずです:

  sat_across([X,_,Y,_], X, Y).
  sat_across([_,X,_,Y], X, Y).

  sat_beside(T, X, Y) :-  % this is tricky
      nth1(N,T,X), nth1(M,T,Y),
      (N =:= M+1 ; N =:= M-1 ; N == 1, M == 4 ; N == 4, M == 1).
      not_connected(T, Place) :- \+ member(Place, T).
  connected(T, Place) :- member(Place, T).

  solve(T) :- T = [_,_,_,_],
      sat_across(T, (danny,_,_), (david,_,_)),
      sat_across(T, (donna,_,_), (doreen,_,_)),
      sat_beside(T, (doreen,_,_), (_,_,steak)),
      connected(T, (_,coke,chicken)),
      sat_across(T, (_,_,lasagna), (_,milk,_)),
      not_connected(T, (david,coffee,_)),
      connected(T, (donna,water,_)),
      not_connected(T, (danny,_,steak)).
4

3 に答える 3

0

パターン マッチングを使用し、各位置に Name、Drink、Food という 3 つの属性を含めます。

次に、[N、S、W、E] テーブル (コントラクト ブリッジ規約の悪用) があり、利用可能なすべての制約を適用する必要があります。この方法で実行できると思います...

sat_across([X,_,Y,_], X, Y).
sat_across([_,X,_,Y], X, Y).
sat_across([X,_,Y,_], Y, X).
sat_across([_,X,_,Y], Y, X).

sat_beside(T, X, Y) :-  % this is tricky
    nth1(N,T,X), nth1(M,T,Y),
    (N =:= M+1 ; N =:= M-1 ; N == 1, M == 4 ; N == 4, M == 1).

cant_afford(T, Place) :- \+ member(Place, T).

solve(T) :- T = [N,S,W,E],
      sat_across(T, (danny,_,_), (david,_,_)),
      sat_across(T, (donna,_,_), (doreen,_,_)),
      sat_beside(T, (doreen,_,_), (_,_,steak)),
      ....
      cant_afford(T, (danny,_,steak)),
      ....
于 2012-10-02T16:06:03.833 に答える
0

申し訳ありませんが、私がこのスレッドをネクロしている場合は、回答に満足していませんでした (洗練されていない/不完全なようです)。

これはゼブラ問題の変種です。唯一の真の問題は、「X がどの位置にいるか」であり、X は人、メインディッシュ、または飲み物である可能性があります。したがって、ドメインは { 1, 2, 3, 4 } となり、各数字は座席を表します。

次に、制約を追加し、各アイテムが同じタイプの他のアイテムに対して固有の位置にあることを確認し (つまり、人は 1 席にしか座れないなど)、プロローグを緩めます。

ああ、負の制約を最後に置くことを忘れないでください。これが私が最終的に得たものです:

%  Organize the seating, so:
%  1  2
%  3  4
%  This means that "across" is always (n+2)%4
%  and "beside" is (n+1)%2

pos(1). pos(2). pos(3). pos(4).

beside(A,B) :- pos(A), B is (A+1) mod 2.
across(A,B) :- pos(A), B is (A+2) mod 4.

zebra(Donna,Danny,David,Doreen,
     Steak,Lasagna,Pizza,Chicken,
     Coke,Milk,Coffee,Water) :-
  % Our 4 given positive constraints
  beside(Doreen,Steak),
  Chicken=Coke,
  across(Lasagna,Milk),
  Donna=Water,
  % The men and women sat across from each other
  across(David,Danny),
  across(Doreen,Donna),
  % Ensure that each item is only in 1 position
  uniq_pos(Steak,Lasagna,Pizza,Chicken),
  uniq_pos(Coke,Milk,Coffee,Water),
  uniq_pos(Donna,Danny,David,Doreen),
  % The remaining two negative constraints.
  \+ David=Coffee,
  \+ Danny=Steak.

% Ensures that all 4 items are in unique positions.
uniq_pos(A,B,C,D) :-
  pos(A), pos(B), pos(C), pos(D),
  \+ A=B, \+ A=C, \+ A=D,
          \+ B=C, \+ B=D,
                  \+ C=D.

うまくいくようです。プロローグによると、
デビッドは 1 番席でステーキと牛乳、
ドリーンは 2 番席でチキンとコーラ、
3 番席でダニーはラザニアとコーヒー、
4 番席でドナはピザと水をもらった。

これが、この問題を理解しようとしている他の誰かに役立つことを願っています。

于 2013-10-03T08:34:05.280 に答える
0

この問題には 8 つの変数があることを認識しておく必要があります。各人の飲み物とメイン コースDonnaDrinkなどDannyFoodです。

あなたのプログラムは、これらの 8 つの変数を与えられた事実に従って制限する必要が=あります。\=gender

(これは実際にはゼブラ パズルの単純な変形ですが、すべての順序はありません。)

于 2012-10-02T15:14:12.993 に答える