2016-05-31 91 views
1

所以我不期望今天发布更多,但我不知道做这个任务,我傻了。我有工作代码旅行输入列表3乘3元素。但我只是意识到它只适用于3个元素的列表,当我输入4时失败。说得通。因此,我试图制定一个规则,逐个接收每个元素,以这种方式传送两个列表,并且由于这两个列表同样长,所以它们应该同时停止,并且我的输出列表应该与之前一样!如何旅行一个列表n由n元素

但不是一个机会,它直线上升失败。我认为我以错误的方式看待这个问题,因为这不是一件非常困难的事情。

原来,工作了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). 

而一丝痕迹,令我d目结舌,对我而言,这难以为继:

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) 

基本上,因为我一直在做类似的操作,但是这个直接失败了。我想这是因为统一或基本情况?但是我没有看到与其他列表有很大差异,我可以看到他们是如何旅行和工作的,所以并不真正了解这方面的问题。

回答

1

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

因此,它应该是这样的:

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

,如果它要对空列表调用。这使得WAY的时间超过了它应该的时间。

+0

我以某种方式怀疑这是正确的解决方案。最好是使用[tag:dcg]来描述列表,或者进一步实例化给定列表。后者意味着你可能会在某个地方有一个像'Ls = [First | Rest]这样的目标,或者像这个子句的* head *中的[First | Rest]这样的模式。 – mat

+0

我能否看到一些已经完成的例子,以进一步实例化给定的列表?我觉得这样会让我的代码更容易阅读,但它也是性能,但现在我坚持使用这种解决方案(就像我现在认为这是解决这类问题的方法,并且不真的看到另一个)。至于dcg,我可能会尝试它,但我不确定我会掌握它的时间,我有:( – keont

3

在这种情况下的基金问题是,[First|Rest]意味着不同于你认为的 。这意味着列表的第一个元素First。它确实是而不是的意思是“以的元素First开始的列表”。因此,如果First本身是列表,则[First|Rest]是其列表的第一个元件是列表。

该问题特别体现在[EnumsFormados|EntradaCreacionEnum],其中EnumsFormados本身的一个列表。

Reasonsing有关贯穿多个谓词的描述可以很容易出错和繁琐,因为这个原因列表,我们有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发生在所描述的列表中的该位置。