列表中的唯一元素(Prolog)

Posted

技术标签:

【中文标题】列表中的唯一元素(Prolog)【英文标题】:Unique elements in list (Prolog) 【发布时间】:2011-05-23 13:55:57 【问题描述】:

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

当尝试计算解决方案时,我尝试这样做:

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 看起来像:house(x , food, pet ,sport),5 看起来像:house(_, flower, pet, sport)

我还尝试将其添加到提示中:(假设“仙人掌”是提示中未提及的花之一) member(house(cactus,_,_,_), Street)

但是我的程序并没有结束......

提示可能如下所示: is_neighbour(house(_,_,_,football),house(_,_,fish,_), Street), 当 A 和 B 在 List 中彼此相邻时,is_neighbour(A,B,List) 给出 true。 提示可以翻译为:热爱足球的人住在有鱼的人旁边。

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

【问题讨论】:

【参考方案1】:

要表示没有花两次被报告,并且确保所有花都被绑定,可以使用 permutation/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 分钟。)我把 permutation 放在哪里重要吗? 两个参数的排列应该是对称的,因此交换参数应该没有帮助。但是,将排列调用放在不同的位置应该会有很大帮助:您应该首先放置那些最限制解决方案空间的条件。将 write 调用放入其中以使其跟踪正在执行的操作。 当我在它给出的提示末尾的排列周围放置一个 call(write()) 时: permutation([geranium,hyacint,lelie,dahlia,lelie],[仙人掌,lelie,天竺葵,风信子,大丽花])。当我把它放在它给我的所有提示前面时:排列([_46,_53,_60,_67,_74],[仙人掌,lelie,天竺葵,风信子,大丽花])。我不确定第一个是什么意思。输出仍然给我 2 x,但它现在结束了。我是否还需要为其他类型添加排列才能使这个单一排列起作用? 不确定你所说的写“围绕”排列()是什么意思。您是说您将排列用作仅打印出来的结构吗?您应该将其评估为谓词,并将打印 放在 之后,而不是围绕排列。 我很确定我在写的东西上做错了。这是我的代码:pastebin.com/5TjJJ5nj(它很长,但所有的东西都是相似的,所以阅读时可以很快跳过),你能告诉我我把这个写在哪里吗?另外我应该把什么作为写的参数,因为当我不传递任何参数时它会给我一个错误......

以上是关于列表中的唯一元素(Prolog)的主要内容,如果未能解决你的问题,请参考以下文章

Prolog中的列表练习列表

Prolog中的展平列表[重复]

如何通过Prolog将字符串连接到列表中的多个元素?

尝试使用prolog将变量分配/提取到列表列表中的不同元素

Prolog 中的前缀

Prolog 中的子列表谓词