Prolog中的逻辑难题——使用列表

Prolog中的逻辑难题——使用列表,prolog,zebra-puzzle,program-slicing,Prolog,Zebra Puzzle,Program Slicing,我正试图用Prolog解决以下问题,我认为我的代码编写正确,但我的查询只返回false。有什么改变的建议吗?问题如下: “百吉饼巷,当地的百吉饼店,在节日期间一直是一个活动猖獗的地方 早上的通勤时间,人们停下来在路边买咖啡和百吉饼 工作方式。每天早上现场制作新鲜的百吉饼,非常受欢迎,也非常美味 事实上,这家商店也有很棒的咖啡,就像蛋糕上的糖霜一样 在百吉坊工作的人都很开朗、友好,而且能干,所以 尽管顾客很多,但等待的时间从来都不长也不令人不快 今天早上他的四个同事过来看看每个人都做了些什么 他们

我正试图用Prolog解决以下问题,我认为我的代码编写正确,但我的查询只返回false。有什么改变的建议吗?问题如下:

“百吉饼巷,当地的百吉饼店,在节日期间一直是一个活动猖獗的地方 早上的通勤时间,人们停下来在路边买咖啡和百吉饼 工作方式。每天早上现场制作新鲜的百吉饼,非常受欢迎,也非常美味 事实上,这家商店也有很棒的咖啡,就像蛋糕上的糖霜一样 在百吉坊工作的人都很开朗、友好,而且能干,所以 尽管顾客很多,但等待的时间从来都不长也不令人不快 今天早上他的四个同事过来看看每个人都做了些什么 他们到处胡言乱语,惊喜地发现这家商店没有辜负他们的期望 声誉。确定每个同事的名字,用它的名字做什么样的百吉饼 浇头,以及每种咖啡的口味和大小(小、中、大)。”

  • 布拉德得到了他的百吉饼,它不是小麦,上面什么也没有。沃尔特点了一小杯咖啡

  • 两位同事喝的是中等大小的咖啡,一位是榛子口味的,另一位是花生百吉饼 黄油

  • 有洋葱百吉饼但不加黄油的人也有法国香草咖啡,但不是小号的

  • 这五位同事是乔,一位喝了大杯咖啡,一位喝了苦杏仁口味的咖啡,一位吃了小麦百吉饼, 还有那个在百吉饼上放鸡蛋和培根的人

  • 瑞克没有点蓝莓百吉饼,但他确实点了哥伦比亚咖啡。苦杏仁咖啡是和切达百吉饼一起点的,但是 不是沃尔特写的

  • 奶油奶酪并没有和蓝莓百吉饼一起上桌,而是和一大杯咖啡一起上桌。芝麻面包圈里有黄油,但是 卡洛斯没有点

  • 我编写的序言代码如下:

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

    我相信运行查询“bagels(X)”,应该可以为我提供问题的解决方案,但它返回false。我错过什么了吗?非常感谢

    首先,问题陈述似乎需要一些审查——特别是第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).
    我试图提高可读性,使用DCG传递状态(在中查找“隐式传递状态”),因此此代码段与您的解决方案非常不同

    你可以看到负面知识以两种不同的方式表达:当涉及到人时,我们可以直接使用
    \=
    ,因为名字总是被实例化,但是对于其他值,比如
    kind(brad,K)
    ,我使用
    {dif(K,小麦)}
    ,因为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)], _).
    
    唉,我得到了太多的解决方案。。。也许我的提示翻译中有一个bug,或者所有不同的属性也应该应用于所有属性,就像提示n.4一样

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

    我懂了。。。那么,您是否认为问题在于给定的问题过于具体,并且在措辞上存在错误?我不确定从你的概括到哪里去,因为它不能满足谜题的要求,除非我将删除的行添加回。@guypowermister:这个概括的要点是:只要剩下的可见部分没有修改,问题就会继续存在。所以你必须在剩下的可见部分做些改变。看看剩下的代码:
    amaretto
    -我觉得connexion很奇怪!你说:
    joe
    amaretto
    但是,有人不是
    joe
    ,那家伙也应该有
    amaretto
    ,哦!这实际上可能就是问题所在。这意味着joe没有苦杏仁酒,但我在编写代码时错过了“\”。@guypowermister:这只是试图保持答案简短的功能。
    ?- aggregate(count,S^bagels(S),N).
    N = 7.