如何通过n个元素旅行列表

时间:2016-05-31 11:10:10

标签: list prolog

所以我没想到今天发布的内容会更多,但是我无法完成这项任务。我有工作代码来输入3个元素的输入列表。但我刚刚意识到它只适用于3个元素的列表,当我输入4时它失败了。说得通。所以我试图制定一个规则,逐个采用每个元素,以这种方式遍历两个列表,并且因为两个列表同样长,所以它们应该同时停止,并且我的输出列表应该像以前一样形成!

但不是偶然,它直接失败了。我认为我以错误的方式看待这个问题,因为这不是一项艰巨的任务。

3个元素的原创,工作理念:

crearEnum(_, [], []).
crearEnum([Ha,Hb,Hc], [[H1,H2,H3]| PermNodes], [[enum(H1,Ha), enum(H2,Hb), enum(H3,Hc)] |SalidaCreacionEnum]):-
    crearEnum([Ha,Hb,Hc], PermNodes, SalidaCreacionEnum).

到目前为止我得到了什么:

我称之为(这是更大规则的一部分):

crearEnum(NodeListUnique, IDsPermuted, [], SalidaCreacionEnum),


crearEnum(_, [], L, L).
crearEnum(NodeListUnique, [CabezaPermNodes| PermNodes], [EnumsFormados |EntradaCreacionEnum], SalidaCreacionEnum):-
    formaEnums(NodeListUnique, CabezaPermNodes, EnumsFormados),
    crearEnum(NodeListUnique, PermNodes, EntradaCreacionEnum, SalidaCreacionEnum).

formaEnums([],[],_).
formaEnums([Ha|NodeListUnique], [H1|CabezaPermNodes], [enum(H1,Ha)|EnumsFormados]):-
    formaEnums(NodeListUnique, CabezaPermNodes, EnumsFormados).

这一点我觉得我很难傻到这一点:

Call:crearEnum([c, b, a], [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]], [], _G5349)
 Fail:crearEnum([c, b, a], [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]], [], _G5349)

基本上因为我一直在做类似的操作,但是这一次直接失败了。我想这是因为统一或基本情况?但是我没有看到与其他列表有太大差异我确实看到了如何旅行并且它们有效,所以不知道这有什么错误。

2 个答案:

答案 0 :(得分:3)

此案例中的基金会问题是[First|Rest]意味着与您认为不同的东西。它表示第一个元素First的列表。它表示“以First中包含 元素开头的列表”。因此,如果First本身是列表,则[First|Rest]是一个列表,其第一个元素是一个列表。

问题尤其体现在[EnumsFormados|EntradaCreacionEnum],其中EnumsFormados 本身是一个列表。

在多个谓词中描述的列表的原因可能非常容易出错并且很麻烦,因此,我们在Prolog中有 DCG表示法):它使描述列表更容易,特别是如果单个列表的描述跨越多个规则。

我举一个与你的用例松散相关的例子。通过少量修改,您可以使用此DCG来描述对您而言重要的列表。我将描述enum(Unique,Node)形式的术语列表。

enums([], _) --> [].
enums([U|Us], Nodes) -->
    enums_(Nodes, U),
    enums(Us, Nodes).

enums_([], _) --> [].
enums_([N|Nodes], U) -->
    [enum(U,N)],
    enums_(Nodes, U).

示例查询和回答:

?- phrase(enums([a,b], [x,y,z]), Ls).
Ls = [enum(a, x), enum(a, y), enum(a, z), enum(b, x), enum(b, y), enum(b, z)].

请注意,参数不需要具有相同的长度!另请注意,该定义跨越多个子句,但很容易描述列表的元素。 DCG语法 [Terminal] 用于表明特定Prolog术语Terminal出现在所描述列表中的该位置。

答案 1 :(得分:1)

好的,找到了。我试图将空列表的头尾分开,所以答案是,它失败了,无法完成。

所以它应该是这样的:

crearEnum(NodeListUnique, [CabezaPermNodes| PermNodes], [EntradaCreacionEnum], SalidaCreacionEnum):-

如果要用空列表调用它。这花费的时间比它应该的长。