通过单个元素扩展列表列表

时间:2018-04-30 19:34:01

标签: prolog

我正在尝试在ProLog中解决以下问题。我是初学者。

定义谓词extend,以便XssYss列出 然后,如果extend(X, Xss, Yss)可以通过添加Yss获得,则X成立 元素Xss?- extend(g, [[e], [b, c, f], [k, h]], Yss). Yss = [[e, g], [b, c, f, g], [k, h, g]] 中每个元素的末尾,例如

extend(X, [], []).

extend(X, [[Firstxss,_] | Restxss], Yss) :-
    Firstxss is [Firstxss,_|X],
    Yss is  [Yss | [Firstxss,_]],        
    Xss is Restxss,
    extend(X, Xss, Yss).

我尝试使用以下内容,但是有一条错误消息:

?- extend(g, [[e], [b, c, f], [k, h]], Yss).

我输入了以下内容:

false.

然后它返回:

false.

我认为我有一个有效的输入,我不明白为什么它会以char array1[4]; // ... array1[3] = 0;

的形式返回

2 个答案:

答案 0 :(得分:3)

由于你想对外部列表的每个元素做同样的事情,这对maplist/3来说是一个非常漂亮的任务。您可以使用append/3通过其他元素扩展列表,如下所示:

?- append([1,2],[element],Z).
Z = [1, 2, element].

但是,您希望append/3中有两个缺少参数的maplist/3,因此将第一个参数附加到第二个参数是合适的。要实现这一点,你可以编写一个辅助谓词,调用append/3并翻转前两个参数,例如:

flippedappend(X,Y,Z) :-
   append(Y,X,Z).

在此基础上,您可以像这样定义实际关系:

x_lists_extended(X,Xss,Yss) :-
   maplist(flippedappend([X]),Xss,Yss).

您的示例查询会产生所需的结果:

?- x_lists_extended(g, [[e], [b, c, f], [k, h]], Yss).
Yss = [[e, g], [b, c, f, g], [k, h, g]].

请注意,您也可以反过来使用此谓词:

?- x_lists_extended(X, Xss, [[e, g], [b, c, f, g], [k, h, g]]).
X = g,
Xss = [[e], [b, c, f], [k, h]] ;
false.

答案 1 :(得分:1)

首先,这里有一个单例变量X

extend(X, [], []).

最好说extend(_, [], []),因为你再也不会引用X.了解为什么会这样,这很重要。在Prolog中,所有操作都是由于变量所在的关系而发生的。如果变量只出现在一个地方,那么它就不会参与任何关系,因此应该用_替换。 (如果你进行了这样的修改并且代码似乎是无稽之谈,请停止并研究它,因为它总是意味着你误解了某些东西。)

其次,is/2用于评估算术表达式。这里没有数学:Firstxss is [Firstxss,_|X]所以你把它与=混淆了。这真是一个双重打击,因为= 意味着在Prolog中分配,这意味着统一。因此Prolog中没有真正的情况,你会有X = X+1或类似的东西,这正是你在这里做的事情,试图为不同的目的重用一个变量。

本条款中Firstxss的含义是什么?看起来它是头部第二个参数中嵌套列表中的第一个项目:换句话说,如果您调用了extend(g, [[e], [b, c, f], [k, h]], Yss),那么Firstxss = e Firstxss的值永远不会改变。它只能在递归调用中反弹。因此,当您立即说Firstxss is [Firstxss,_|X]时,Prolog看到的是b = [b,_|<another var>]。这并没有统一,你的谓词在这一点上失败了。不管怎样,说它先进了。你在Yss的下一行犯了同样的错误。

有助于从关系上思考你的问题。你也有错误的基础案例。你的基本案例是什么?这是你到达列表末尾的情况,你应该怎么做?附加X.所以这是你的基本情况:

extend(X, [], [X]).

现在想想在其他情况下你想做什么:你有头和尾。你是如何延伸的?你延长尾巴,你的结果是附加在延长尾巴上的头部。自己尝试写下这个条款,并不困难!

一旦你有了这个,扩展嵌套列表的机制很简单:你测试头部是否是一个列表。如果是的话,重复头部和尾部!像这样:

extend(X, [Y|Ys], Result) :-
  (is_list(Y) -> extend(X, Y, Y1) ; Y1 = Y),
  ... % use Y1 as Y in building the result