2016-04-15 73 views
2

我想在Prolog中解决以下问题,并且我认为我已经编写了正确的代码,但我的查询只是返回false。有什么建议要改变?问题是如下:Prolog中的逻辑谜题 - 使用列表

“贝果巷,当地的面包圈店,总是怒不可遏活动的位置时 早晨通勤的人停下来让他们的咖啡和面包圈在上班的 方式新鲜制作在现场每天早晨,百吉饼是非常受欢迎, 的事实店也有很大的咖啡就像锦上添花!谁在贝果巷工作的人 是开朗和友善,以及胜任,所以 尽管大量的客户,等待是永远长或不愉快。乔 和他的同事今天早上停的四看什么大家都 热烈讨论,并惊喜地发现,笑p达到了其声望。确定每个同事的名字,每个有序什么样以其 馅料面包圈,什么味道的咖啡尺寸(小,中,大)“。

  1. 布拉德得到了他的面包圈,这WASN”牛逼小麦,没事就可以了。沃尔特有序的小咖啡。

  2. 两个同事谁得到了中型咖啡是一个谁得到了榛子的味道,谁得到了他的百吉饼花生 黄油。

  3. 的一个
  4. 那个得到洋葱百吉饼,但没有用黄油的人也得到了法国香草咖啡,但不是小尺寸。

  5. 五个同事是乔,谁得到了较大的咖啡之一,谁得到了杏仁味咖啡的人,一个谁得到了小麦面包圈, ,谁在他的百吉饼了鸡蛋&培根的一个。

  6. 瑞克未订购的蓝莓面包圈,但他却获得哥伦比亚咖啡。 Amaretto咖啡与切达干酪百吉饼一起订购,但不是由沃尔特制作而是 。

  7. 奶油奶酪没有配备蓝莓面包圈,但它并配备了一大杯咖啡。芝麻百吉饼配上黄油,但是卡洛斯并没有下令。

我已经写了序言代码是在这里:

bagels(Sol):- 
    Sol = [[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_]], 
    member([brad,X,plain,_,_], Sol), X \== wheat, 
    member([walt,_,_,small,_], Sol), 
    member([_,_,_,medium1,hazelnut], Sol), 
    member([_,_,peanut_butter,medium2,_], Sol), 
    member([_,onion,Y,Z,french_vanilla], Sol), Y \== butter, Z \== small, 
    member([joe,Ja,Jb,Jc,Jd], Sol),Ja\==wheat,Jb\==egg_bacon,Jc\==large,Jd==amaretto, 
    member([La,Lb,Lc,large,Ld], Sol), La\==joe,Lb\==wheat,Lc\==egg_bacon,Ld\==amaretto, 
    member([Aa,Ab,Ac,Ad,amaretto], Sol), Aa\==joe,Ab\==wheat,Ac\==egg_bacon,Ad\==large, 
    member([Wa,wheat,Wb,Wc,Wd], Sol), Wa\==joe,Wb\==egg_bacon,Wc\==large,Wd\==amaretto, 
    member([Ea,Eb,egg_bacon,Ec,Ed], Sol), Ea\==joe,Eb\==wheat,Ec\==large,Ed\==amaretto, 
    member([rick,R,_,_,columbian], Sol),R\==blueberry, 
    member([A,cheddar,_,_,amaretto], Sol), A\==walt, 
    member([_,B,cream_cheese,large,_], Sol), B\==blueberry, 
    member([C,sesame,butter,_,_], Sol), C \== carlos, 
    member([_,_,_,other,_], Sol), 
    member([_,_,_,_,other], Sol). 

我相信,运行查询 “百吉饼(X)”。应该给我解决问题的办法,但它会返回错误。我错过了什么吗?提前谢谢了!

回答

3

首先,似乎问题陈述需要一些回顾 - 特别是点4

你在这里什么是逻辑谜。因此,您确实需要坚持Prolog的逻辑部分。然而,在你的代码中我看到(\==)/2(==)/2,它们都没有完全实现它们假装代表的逻辑关系。相反,分别使用dif/2(=)/2

但即使更换后,事情并没有好多少,你的程序仍然失败。但是,对于纯粹的定义,您有机会本地化的问题。你的问题是bagels(Sols)失败。因此,目前的定义过于专业化,过于狭窄。所以我会尝试通过删除一些要求来推广它。为此,我会在您的一些目标前添加*。我会将它们概括为使得最终的程序仍然失败。

剩下的是一个泛化,告诉你你将在哪里来修改你的程序。否则,错误将会持续。

编辑:我突出显示了什么看起来特别奇怪:两个男人喝阿马雷。

 
:- op(950, fy, *). 
*_. 

bagels(Sol):- 
    Sol = [[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_]], 
    member([brad,X,plain,_,_], Sol), 
     dif(X,wheat), 
    member([walt,_,_,small,_], Sol), 
    member([_,_,_,medium1,hazelnut], Sol), 
    * member([_,_,peanut_butter,medium2,_], Sol), 
    member([_,onion,Y,Z,french_vanilla], Sol), 
     * dif(Y,butter), 
     dif(Z,small), 
    member([joe,Ja,Jb,Jc,Jd], Sol), 
     * dif(Ja,wheat), * dif(Jb,egg_bacon), 
     dif(Jc,large), 
     Jd=amaretto, 
    * member([La,Lb,Lc,large,Ld], Sol), 
     * dif(La,joe), * dif(Lb,wheat), * dif(Lc,egg_bacon), * dif(Ld,amaretto), 
    member([Aa,Ab,Ac,Ad,amaretto], Sol), 
     dif(Aa,joe), 
     * dif(Ab,wheat), * dif(Ac,egg_bacon), * dif(Ad,large), 
    member([Wa,wheat,Wb,Wc,Wd], Sol), 
     * dif(Wa, joe), * dif(Wb, egg_bacon), 
     dif(Wc, large), 
     dif(Wd, amaretto), 
    member([Ea,Eb,egg_bacon,Ec,Ed], Sol), 
     * dif(Ea, joe), 
     dif(Eb, wheat), 
     * dif(Ec, large), 
     dif(Ed, amaretto), 
    member([rick,R,_,_,columbian], Sol), 
     * dif(R,blueberry), 
    * member([A,cheddar,_,_,amaretto], Sol), 
     * dif(A,walt), 
    member([_,B,cream_cheese,large,_], Sol), 
     * dif(B,blueberry), 
    * member([C,sesame,butter,_,_], Sol), 
     * dif(C, carlos), 
    * member([_,_,_,other,_], Sol), 
    * member([_,_,_,_,other], Sol). 

不过,您可能会不高兴:为什么还有这么多的代码?原因是你忘了在开始时提出一些一般的观察。特别是他们想要所有不同的打顶。有了这些信息,程序片段就会缩小到突出显示的行。但是,必须使用library(lambda)开始以下目标。

bagels(Sol):- 
    Sol = [[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_],[_,_,_,_,_]], 
    maplist(Sol+\P^member([P|_], Sol), 
      [brad,walt,joe,rick,carlos]), 
    maplist(Sol+\D^member([_,_,_,_,D], Sol), 
      [amaretto,french_vanilla,hazelnut,columbian,other]), 
    ... 
+0

我明白了......所以你认为问题在于给定的问题过于具体,并且在措辞方面存在错误?我不确定从泛化到何处,因为它不能满足谜题的要求,除非我添加删除的线。 – guypowermister

+1

@guypowermister:这种泛化的要点是:只要剩下的可见部分不是修改后,问题将持续。所以你必须改变剩下的可见部分。 – false

+1

看看其余的代码:'amaretto'-connexion对我来说看起来很奇怪!你说:有'amaeto'的'joe',但是有一个人不是**'joe',那个人也应该有'amaretto' ... – false

1

我试图提高可读性,采用DCG是传递状态(寻找在this page“含蓄通过状态各地”),所以这个片段是不是你的解决方案有很大不同。

你可以看到,知识espressed两种不同的方式:那里的人参与,我们可以直接使用\=,因为名字总是被实例化,但对于其他的值,比如kind(brad, K),我用{dif(K, wheat)},由于K可能还没有实例化。

state(S), [state(T)] --> [state(T)], {member(S, T)}. 

kind(P, K) --> state([P, K, _, _, _]). 
topping(P, T) --> state([P, _, T, _, _]). 
flavor(P, F) --> state([P, _, _, F, _]). 
size(P, S) --> state([P, _, _, _, S]). 


hint1 --> 
    kind(brad, K), {dif(K, wheat)}, topping(brad, plain), size(walt, small). 
hint2 --> 
    size(P1, medium), size(P2, medium), {P1 \= P2}, 
    flavor(P1, hazelnut), topping(P2, peanut_butter). 
hint3 --> 
    kind(P, onion), flavor(P, french_vanilla), size(P, S), {dif(S, small)}. 
hint4 --> 
    size(P1, large), flavor(P2, amaretto), kind(P3, wheat), topping(P4, egg_bacon), 
    {forall(select(X, [joe,P1,P2,P3,P4], Ps), maplist(\=(X), Ps))}. 
hint5 --> 
    kind(rick, K), {dif(K, blueberry)}, flavor(rick, columbian), 
    kind(P, cheddar), flavor(P, amaretto), {P \= walt}. 
hint6 --> 
    topping(P1, cream_cheese), kind(P2, blueberry), {P1 \= P2}, size(P1, large), 
    kind(P, sesame), topping(P, butter), {P \= carlos}. 

bagels(Sol):- Sol = 
    [[brad,_,_,_,_], 
    [walt,_,_,_,_], 
    [joe,_,_,_,_], 
    [rick,_,_,_,_], 
    [carlos,_,_,_,_]], 
    phrase((hint1, hint2, hint3, hint4, hint5, hint6), [state(Sol)], _). 

唉,我得到了太多的解决方案......也许有我的提示翻译中的错误,或者在all_different应适用于所有的属性,以及用于提示N.4做

?- aggregate(count,S^bagels(S),N). 
N = 7.