繁体   English   中英

Prolog谓词解决方案

[英]Prolog Predicate Solution

我正在为即将到来的Prolog考试解决一些过去的考试问题。

这是问题:

  1. (a)编写一个谓词insert(Xs, Y, Zs) ,该谓词在Zs是通过将Y插入列表Xs中获得的列表时成立。 查询,例如:

     ? - insert([1,2,3], 4, Zs). 

应该成功四次,并给出以下答案:

Zs = [4, 1, 2, 3]

Zs = [1, 4, 2, 3]

Zs = [1, 2, 4, 3]

Zs = [1, 2, 3, 4]. 

我有点担心,因为我不知道从哪里开始。 在我需要示例解决方案来练习考试的过程中,有人可以提供帮助吗?

非常感谢您的帮助。

我们从更改此谓词的可怕名称开始:谓词应描述什么成立而不是做什么。 名称应反映出这一点。 我建议使用list_with_element/3 ,并鼓励您尝试寻找更好的名称,最好是明确每个参数的含义。

然后,我们要做我们打算做的事情:描述使这种关系成立的情况。

例如:

list_with_element([], E, [E]).
list_with_element([L|Ls], E, [E,L|Ls]).
list_with_element([L|Ls0], E, [L|Ls]) :-
        ...

我留在填写...作为一个简单练习。 说明子句头为真所必需的条件!

编辑 :我想说更多有关上述模式。 以我的经验,推论描述列表的谓词的一种好方法(绝对是在开始时)是考虑以下两种基本情况:

  1. 原子[] ,表示空列表
  2. 形式为'.'(E, Es)术语,也写为[E|Es] ,其中E是列表的第一个元素, Es也是列表。

这遵循列表的归纳定义。

在这种特定情况下的缺点是,这种方法导致情况再次需要将情况(2)分为两个子情况,并且以某种方式意外地需要三个子句来处理这两个基本情况。 显然,这与我们直觉地期望两个子句就足够相反。 的确确实如此,但是我们需要注意不要意外丢失解决方案。 在这种情况下,上面的前两个子句包含在以下事实中:

list_with_element(Ls, E, [E|Ls]).

每个有经验的Prolog编码器都将以这种方式编写谓词,或者仅在这种情况下直接使用select/3 这就是@lurker的感知和暗示,而@tas正确地表明了一个不同的子句(很容易意外地想到)并没有完全包含我们要表达的所有情况。

因此,我仍然发现首先明确考虑空列表,确保正确设置大小写,然后继续处理更复杂的情况,然后查看是否可以更紧凑地编写现有程序,要容易得多。 这也是我用于此示例代码的方式,但是我没有使其尽可能短。 请注意,对于单调代码,有多余的事实是完全可以的!

请注意,是专门为没有确定,只是通过更换前两个条款:

list_with_element([L|Ls], E, [E|Ls]).

因为此子句不包含上述情况(1)。

我猜想这个问题可能正在寻找的一个答案遵循以下思路:

insert(List, Element, NewList) :-
    append(Front, Back, List), % split list in two
    append(Front, [Element|Back], NewList). % reassemble list

如果您希望声明式阅读:

NewList在List的前后之间具有Element。

仔细检查是否在先前的问题或学习材料中出现了append/3或具有相同语义的谓词。

并请注意,如果我正确理解的话,这实际上与@mat建议完全相同 有关详细信息,请查阅append/3的教科书定义。 甚至更好的是,查看append/3的教科书定义, append/3其修改为在“插入”时使用。

尽管参数的顺序不同,但内置的谓词select/3可以执行相同的操作。

请记住,(如果定义正确)谓词可以在不同方向上工作。 例如,它可以告诉你一个列表看起来像移除元素后,它可以(尽管这也很简单)告诉您从一个列表中删除哪些因素再弄,也可以告诉你列出,有后给定元素被删除,将类似于给定列表。
(提示:您可能要研究最后一个)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM