【问题标题】:Solving a puzzle in Prolog在 Prolog 中解决一个难题
【发布时间】:2016-11-14 22:48:37
【问题描述】:

我是 prolog 的新手,我正在尝试解决这个难题。我在 youtube 上做了一些关于 prolog 基础的教程,但我需要一些帮助来解决下面的难题。

两周前,四位爱好者在他们附近的天空中目击了天体。这四个人都在不同的日子报告了他或她的目击事件。联邦调查局来了,能够给每个人不同的解释,说明他或她“真正”看到了什么。你能确定每个人在哪一天(周二到周五)看到这个物体,以及它原来是那个物体吗?

  1. 先生K 在本周早些时候的某个时间比看到气球的人发现了他,但在本周晚些时候的某个时间,比发现风筝的人(不是 G 女士)。
  2. 星期五的目击事件是由 Barn 女士或看到飞机的人(或两者兼有)发现的。
  3. 先生Nik 周二没有出现。
  4. 先生K 不是那个对象原来是电线杆的人。

我已经正确设置了我的规则,但我似乎无法理解逻辑。我正在寻找指导而不是直接答案。在最右边,我列出了我试图回答的每个问题的编号

        enthu(mr_k).
        enthu(ms_barn).
        enthu(ms_g).
        enthu(mr_nik).

        object(ballon).
        object(kite).
        object(plane).
        object(tele_pole).

        day(tuesday).
        day(wednesday).
        day(thursday).
        day(friday).



        sight(X,ballon).

        sighting(mr_k):-   1
        day(X),
        sight(X,Y),
        didntc_kite(ms_g).

        friday_sight:- enthu(ms_barn);    2
        saw(X,plane);
        both(ms_barn,X).


        nosight_tuesday(mr_nik,X).          3

        no_telepole(mr_k,Y).          4

【问题讨论】:

  • 你第一次声明这个mr_klien而不是mr_k有什么原因吗?
  • 啊哈,这就是我复制和粘贴不正确的结果。已更新。
  • 什么是“逻辑压缩包”?
  • 哦,你的意思是“向下拍”吗?
  • 指针 1:看看你是否可以用sighting 作为感兴趣的动作/对象重写你的规则。例如,而不是说nosight_tuesday(mr_nik,X).。建立规则,使瞄准true ike sighting(mr_nik) :- ... sighting(mr_k) :- ... 等等

标签: prolog zebra-puzzle


【解决方案1】:

我知道您没有要求解决方案,但我发现如果没有可行的解决方案,我很难描述该怎么做。对此我深表歉意。

我会这样做:

/* 1. K 先生在本周早些时候的某个时间比看到气球的人发现了他,但在本周晚些时候的某个时间,比发现风筝的人(不是 G 女士)发现了他的视线。 2. 星期五的目击事件是由 Barn 女士或看到飞机的人(或两者兼有)造成的。 3. Nik 先生周二没有出现。 4. K 先生不是那个对象原来是电线杆的人。 */ ?- % 设置列表列表作为最终解决方案 天数 = [[星期二,_,_],[星期三,_,_],[星期四,_,_],[星期五,_,_]], /* 1 */ before([_,mr_k,_],[_,_,balloon],Days), /* 1 */ before([_,_,kite],[_,mr_k,_],Days), /* 2 */ (member([friday,ms_barn,_],Days); 成员([星期五,_,飞机],天)​​; 成员([星期五,ms_barn,飞机],天)​​), % 填写其余的人 成员([[_,mr_k,_],[_,ms_barn,_],[_,ms_g,_],[_,mr_nik,_]],天), % 填充其余对象 成员([[_,_,气球],[_,_,风筝],[_,_,飞机],[_,_,tele_pole]],天), % 否定应该在解决方案被填充后完成 /* 1 */ 成员([_,NOT_ms_g,kite],Days), NOT_ms_g \= ms_g, /* 3 */ member([tuesday,NOT_mr_nik,_],Days), NOT_mr_nik \= mr_nik, /* 4 */ 成员([_,NOT_mr_k,tele_pole],天), NOT_mr_k \= mr_k, 写(天), nl, 失败。 % 检查 `X` 是否在 `Y` 之前 % 在列表 `Ds` 之前(X,Y,Ds):- 余数(X,Ds,Rs), 成员(Y,Rs)。 % 找到一个列表的成员并且 % 统一第三个参数如 % 它是剩余的元素 % 找到成员之后的列表 余数(X,[X|Ds],Ds)。 余数(X,[_|Ds],Rs):- 余数(X,Ds,Rs)。 % `member` 的扩展版本 % 检查第一个列表的成员是否 % 是第二个的所有成员 成员([],_)。 成员([X|Xs],Ds):- 成员(X,Ds), 成员(Xs,Ds)。

这给了我:

[[星期二,ms_g,tele_pole], [星期三,mr_nik,风筝], [星期四,mr_k,飞机], [星期五,ms_barn,气球]]

【讨论】:

  • 非常感谢您的回答。但这似乎很复杂。你能把它简化一下吗/向我解释一下到底发生了什么。
  • @MichealC。 - 我当然可以,但可能需要几个小时。
  • 好的,这不是问题。但是,当您有机会时,我看到您正在使用数组,此时我已经不在我的范围内了。请简单。
  • @MichealC。此答案中没有数组。这是在 Prolog 中解决这个经典谜题示例的经典方法。互联网上和 stackoverflow 上都有大量类似的难题和解决方案。
  • 正如我所说,这一切都很好,但态度上的某些东西让我很恼火。无论如何,OP 的问题是一个教科书示例,说明了在在 Stackoverflow 之类的论坛中提出问题的错误尝试。
猜你喜欢
  • 2020-04-03
  • 1970-01-01
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
  • 2020-11-16
  • 2011-06-10
  • 2013-08-19
  • 1970-01-01
相关资源
最近更新 更多