列表中的唯一元素(Prolog)

列表中的唯一元素(Prolog),prolog,unique,zebra-puzzle,Prolog,Unique,Zebra Puzzle,我正在实现爱因斯坦谜语的一个变体,我遇到了一些麻烦 在尝试计算解决方案时,我尝试以下方法: solve(Street) :- Street = [_House1,_House2,_House3,_House4,_House5], %hint one goes here %hint two goes here %etc. 然后我可以通过键入:solve(Street)来询问解决方案 然而,这是一个解决方案: 房子(花、食物、宠物、运动) 房子(花、食物、宠物、运动) 房子(x,食物,宠物,运动)

我正在实现爱因斯坦谜语的一个变体,我遇到了一些麻烦

在尝试计算解决方案时,我尝试以下方法:

solve(Street) :- Street = [_House1,_House2,_House3,_House4,_House5],
%hint one goes here
%hint two goes here
%etc.
然后我可以通过键入:solve(Street)来询问解决方案

然而,这是一个解决方案:

  • 房子(花、食物、宠物、运动)
  • 房子(花、食物、宠物、运动)
  • 房子(x,食物,宠物,运动)
  • 房子(花、食物、宠物、运动)
  • 房子(x、花、宠物、运动)
  • 正如你所看到的,有2次x,其余的都是各种各样的食物、鲜花、宠物和运动。 但每种类型都是独一无二的:如果一个人喜欢花X,没有人会喜欢花X

    现在,我的解决方案给出2个x的原因很容易理解:我们得到了大量的提示,但在所有提示中只提到了4朵花。所以Prolog不知道还有另外一朵花,只使用了x两次,因为这是可能的,并且满足了所有其他提示

    我想说的是,街上所有类型的食物和鲜花等都是独一无二的,所以当他已经使用了所有类型时,他应该留下一些空白。3个看起来像:
    房子(x,食物,宠物,运动)
    ,5个看起来像:
    房子(x,花,宠物,运动)

    我还试着在提示中添加以下内容:(假设“仙人掌”是提示中未提及的花朵之一)
    会员(房子(仙人掌街)

    然而,我的计划并没有结束

    提示可能如下所示:
    是邻居(房子(足球),房子(鱼),街道),
    使用:
    是相邻的(A,B,List)
    当A和B在
    列表中相邻时给出
    true
    。 这个暗示可以翻译成:热爱足球的人和养鱼的人住在一起


    如果需要提供更多信息,我愿意详细说明。:)

    要表示没有花被报告两次,也要确保所有花都被绑定,可以使用排列/2谓词:所有花的列表应该是指定花列表的排列。这看起来像[未经测试]

    flowers([], []).
    flowers([house(Flower,_,_,_)|Street], [Flower|Rest]) :- flowers(Street, Rest).
    
    -- ...
       flowers(Street, Flowers), 
       permutation(Flowers, [kaktus, tulpe, nelke, rose, fingerhut]),
    
    编辑:对于10朵花,使用排列可能太慢。另一种方法是

    flower(kaktus).
    flower(tulpe).
    flower(nelke).
    --...
    
           flowers(Street,[F1,F2,F3,F4,F5,F6,F7,F8,F9,F10]),
           flower(F1), flower(F2), F1\=F2,
           flower(F3), F3\=F1, F3\=F2,
           flower(F4), F4\=F1, F4\=F2, F4\=F3,
           --...
    

    听起来这是一个合乎逻辑且可以理解的答案,但我一定是做错了什么。。我在第二个排列列表中添加了所有的花。我还将
    flowers(Street,flowers)
    和排列放入
    solve(Street)
    。但现在它似乎还没有结束。(通常会在5分钟内结束,但现在已经超过15分钟了。)我把
    排列放在哪里有关系吗?
    ?两个参数的排列应该是对称的,所以交换参数应该没有帮助。不过,将置换调用放在不同的位置应该会有很大帮助:您应该首先放置那些最能约束解决方案空间的条件。将写调用放入其中,让它跟踪它在做什么。当我在它给出的提示末尾的排列周围放置一个调用(write())时:排列([天竺葵,风信子,乐莉,大丽花,乐莉],[仙人掌,乐莉,天竺葵,风信子,大丽花])。当我把它放在它给我的所有提示前面时:排列([[u46,[u53,[u60,[u67,[u74],[cactus,lelie,geranium,hyacint,dahlia])。我不知道第一个是什么意思。输出仍然为我提供了2个x,但现在确实结束了。我是否还需要为其他类型添加置换才能使此单一置换生效?不确定您所说的“围绕”置换()写是什么意思。你是说你使用排列作为一种结构,你只是打印出来?你应该把它当作一个谓词来计算,然后把打印放在排列之后,而不是放在排列之后。我很确定我写的东西有问题。。这是我的代码:(很长,但所有的东西都很相似,所以在阅读时可以很快跳过),你能告诉我我把这篇文章放在哪里吗?还有,当我不传递任何参数时,它会给我一个错误,所以我应该把什么作为写入的参数。。。