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

我尝试了一些方法,每个人都有一个与他们相关的列表,你会填写事实,但我认为这不是正确的方法。有人可以帮我完成这个吗?谢谢!

编辑:

这是我最终得到的代码,它完成了大部分难题,它留下了一份主菜和一份饮料,但这应该是可以修复的:

  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

你应该认识到这个问题有八个变量:每个人的饮料和主菜,所以DonnaDrinkDannyFood等等。

=您的程序应该使用并根据给定的事实来约束这八个变量\=,也许使用额外的谓词,例如gender.

(这实际上是斑马拼图的一个简单变体,但没有全部排序。)

于 2012-10-02T15:14:12.993 回答
0

使用模式匹配,每个位置都有一个属性三元组:姓名、饮料、食物。

然后我们有一个 [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 个座位上,等等),并将 prolog 设置为松散。

哦,别忘了把你的负面约束放在最后。这就是我最终得到的结果:

%  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.

似乎工作。Prolog 告诉我:
坐在 1 号座位上的大卫有牛排和牛奶,
坐在 2 号座位上的多琳有鸡肉和可乐,
坐在 3 号座位上的丹尼有烤宽面条和咖啡,
坐在 4 号座位上的唐娜有披萨和水。

希望这可以帮助其他试图理解这个问题的人。

于 2013-10-03T08:34:05.280 回答