我正在接受一些过去的考试问题,以便进行我的prolog考试。
以下是问题:
(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].
应该成功四次并给出以下答案:
using(Something myObject = new Something())
{
PopulateSomethingObject(myObject);
x = myObject.SomeNumber();
}
我有点担心,因为我不知道从哪里开始。任何人都可以提供帮助,因为我需要示例解决方案来练习我的考试。
非常感谢任何帮助。
答案 0 :(得分:3)
我们首先更改此谓词的可怕名称:谓词应描述持有什么,不该做什么。这个名字应该反映出来。我建议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]) :-
...
我将填写...
作为一项简单的练习。陈述条款头是真实所必需的条件!
编辑:我想多说一下上面的模式。根据我的经验,一个很好的方法 - 并且肯定在开始时 - 推理描述列表的谓词是考虑两个基本情况:
[]
,表示空列表'.'(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)。
答案 1 :(得分:1)
我想这个问题可能正在寻找的答案就是这样:
insert(List, Element, NewList) :-
append(Front, Back, List), % split list in two
append(Front, [Element|Back], NewList). % reassemble list
如果您想要声明性阅读:
NewList在List的正面和背面之间有元素。
仔细检查先前的问题或研究材料中是否出现append/3
或具有相同语义的谓词。
请注意,如果我理解正确的话,这本质上是与suggestion by @mat完全相同的解决方案。有关详细信息,请参阅append/3
的教科书定义。或者甚至更好,查看append/3
的教科书定义并对其进行修改,以便用于"插入"。
答案 2 :(得分:1)
有一个内置的谓词select/3
可以做同样的事情,尽管参数的顺序不同。
请记住(如果定义正确)谓词可以在不同的方向上工作。例如,它可以告诉你删除元素后列表的样子,它可以(虽然它相当简单)告诉你要从一个列表中删除哪个元素来获取另一个元素,或者它可以告诉你什么列表,删除给定元素后,将类似于给定列表。
(提示:你可能想看看最后一个)。