序言和逻辑谜题

Posted

技术标签:

【中文标题】序言和逻辑谜题【英文标题】:Prolog and Logic Puzzles 【发布时间】:2018-05-01 02:33:23 【问题描述】:

我似乎对 Prolog 中的事实统一有疑问,但无法确认。一切看起来都应该工作,鉴于 Prolog 的相对稀有性,我查找了使用 Prolog 解决逻辑难题的示例,但没有实际效果。

一个额外的学分分配,所以我不确定它是否有效,但我真的不知道如何从这里开始

% Names
name(teo).
name(mira).
name(bruno).
name(igor).

%Food
food(sandwich).
food(pie).
food(hamburger).
food(pizza).

%Hobby
hobby(crosswords).
hobby(writing).
hobby(reading).
hobby(photography).

%Shirt Colour
shirt(white).
shirt(yellow).
shirt(blue).
shirt(red).

%Other
girl(mira).

student((Name, Food, Hobby, Shirt)) :-
    name(Name), food(Food), hobby(Hobby), shirt(Shirt).

solution(L):-
    length(L,4),
    L= [student(teo, sandwich,_,_),_,_,_],
    member(student(mira, pite, crosswords,_),L),
    member(student(girl(GirlName),_,_,white),L),
    member(student(bruno,_,_,yellow),L),
    member(student(_,hamburger,writing,_),
    L= [_, student(_,pie,_,_),_,_],
    next(student(_,pie,_,_), student(teo,_,_,_), L),
    next(student(bruno,_,_,_), student(_,pizza,_,_), L),
    next(student(_,_,_,white), student(_,pizza,_,_), L),
    member(student(igor,_,reading,_),L),
    next(student(_,_,_,blue), student(girl(GirlName),_,_,_), L).

next(A, B, Ls) :- append(_, [A,B|_], Ls).
next(A, B, Ls) :- append(_, [B,A|_], Ls).

问题在于它不会将solution(L) 视为谓词或规则,而只是一个文本块,所以我什至无法测试它是否正确。我最感兴趣的是为什么它甚至无法运行。

【问题讨论】:

谓词student((Name, Food, Hobby, Shirt)) :- name(Name), food(Food), hobby(Hobby), shirt(Shirt). 应该提供什么目的?你在程序中对student/4 的使用只是作为一个数据结构术语。此外,也没有使用任何较小的事实。如果您说,例如member(student(girl(GirlName),_,_,white),L),Prolog 不会在此上下文中查询girl(GirlName) 以确定GirlName 的哪些值使其为真。在这种情况下,它只是一个术语,而不是查询。 这是有道理的。这是否意味着我可以简单地将事实输入到解决方案中? Like member([mira, pite, crosswords,_], L)? 如果你保持一致,你可以这样做。换句话说,如果您建立一个约定,即您正在使用一个列表,其中第一个元素是名称,第二个是食物等,那么它就可以工作。只要您保持一致,再次使用诸如[name(mira), food(pite), ...] 之类的术语并没有错。只是你的代码目前没有利用你断言的事实来表明哪些食物是有效的食物等。如果你想利用这些事实,在你的代码中的某个地方你想要像 @987654329 这样的东西@ ... 然后[Name, ...]. 这是另一个例子。假设我们采用了描述有效食物、姓名、爱好和衬衫的事实。您可以使用:findall( [Name, Food, Hobby, Shirt], (name(Name), food(Food), hobby(Hobby), shirt(Shirt)), AllPossibleCombinations) 生成有效集合列表。在 Prolog 提示符下尝试一下,看看它是什么样子的。从您的问题中不清楚solution 正在解决什么问题,所以我无法在这方面提供任何提示。 当你说 问题是它不会把 solution(L) 当作谓词或规则,只是一个文本块,我不明白.你这里确实有一个语法错误:member(student(_,hamburger,writing,_), 但除此之外,它看起来像是一个格式完美的 Prolog 规则/谓词。 【参考方案1】:

起初,我认为girl/1 是许多人所说的罪魁祸首。但即使删除所有此类事件,您的定义仍然会失败(并且在修复该语法错误之后)。这是solution(L) 仍然失败的负责部分:

:- op(950, fy, *)。 *(_)。 解决方案(L):- * 长度(L,4), L= [学生(_/*teo*/, 三明治,_,_),_,_,_], 成员(学生(_/*mira*/, pite, _/*crosswords*/,_),L), * 成员(学生(女孩(GirlName),_,_,白色),L), * 成员(学生(布鲁诺,_,_,黄色),L), 成员(学生(_,hamburger,_/*写作*/,_),L), L= [_, 学生(_,pie,_,_)|_/*[_,_]*/], * 下一个(学生(_,pie,_,_), 学生(teo,_,_,_), L), 下一个(_/*学生(布鲁诺,_,_,_)*/, 学生(_,pizza,_,_), L), * 下一个(学生(_,_,_,white), 学生(_,pizza,_,_), L), * member(student(igor,_,reading,_),L), * 下一个(学生(_,_,_,blue),学生(女孩(女孩名),_,_,_),L)。 下一个(A,B,Ls):-追加(_,[A,B|_],Ls)。 下一个(A,B,Ls):-追加(_,[B,A|_],Ls)。

所有的名字都无关紧要,就像他们的爱好一样。真正重要的是食物!

你只有四个地方,但总共有五种食物(三明治、派、派、汉堡包、比萨饼)- 只给我一个!

这是 Prolog 的优点:您可以进行这样的概括以获得清晰的诊断。

【讨论】:

感谢您的帮助! @Riste:确定一下:你知道你可以执行生成的片段吗? 是的。我用解决方案(L)插入了事实和规则,在它之外只留下了应该存在但在为分配的规则中没有提到的事实,比如颜色(红色)。该列表到最后几乎已满,一切都在适当的位置,只留下一个简单的成员([,_,红色],L)将其添加到唯一可用的空间中。

以上是关于序言和逻辑谜题的主要内容,如果未能解决你的问题,请参考以下文章

Prolog 逻辑谜题和约束编程

VC/C++ 裸属性有啥作用?

如何使用 IMAP 仅获取消息的序言和结尾

获取所有连接节点的网络(逻辑谜题)

序言:谋杀之谜解决方案

好书下载:程序员面试逻辑题解析