2012-04-10 45 views
2

的名单我有我的Prolog的一个问题。我需要反转列表中的所有元素。反向名单

实施例:[1,2,[3,4] - > [[4,3],2,1]

我的解决办法:

myReverse([], []). 
myReverse([H|T], X) :- myReverse(T, RT), myAppend(RT, H, X). 

但它仅给出我: [[3,4],2,1] 我想,我需要使用is_list函数和递归调用列表,如果它不是原子的......但我卡住了......你们知道如何写它吗?

+0

什么'SPOJ/3'?我熟悉的领域在线评测,但是当涉及到Prolog的,我迷路了...... – dasblinkenlight 2012-04-10 01:55:05

+0

我已经重新命名为myAppend,功能连接两个列表,并保存结果到十 – nich 2012-04-10 02:10:45

回答

3

差不多。考虑此解决方案:

myReverse([], []) :- !. 

myReverse([H|T], X) :- 
    !, 
    myReverse(H, NewH), 
    myReverse(T, NewT), 
    append(NewT, [NewH], X). 

myReverse(X, X). 

第一子句是基础情况,其中包括一个切口(!)排除,因为最后一个子句的左选择。

第二个子句反转头H,它可能是一个原子或列表。如果H是一个原子,切割后的递归子目标用最后一个子句进行评估,并且原子通过不变。如果H是一个列表,则使用第二个子句对其进行评估,并且所有元素都相反。下一个子目标与列表的其余部分(尾部,T)完全相同,然后使用内置的append/3最终连接。请注意,新的头元素NewH是奇异的,所以需要添加到列表单结构[NewH]为每append/3里面定义的列表上运行。

最后一个条款通过了所有其他事物(即原子,数字等 - 不是列表或变量的任何东西)。

2
revall(L, Y) :- 
    revall(L, [], Y). 
revall([], Y, Y). 
revall([H|T], T2, Y) :- 
    is_list(H),!, 
    revall(H, Hr), 
    revall(T, [Hr|T2], Y). 
revall([H|T], T2, Y) :- 
    revall(T, [H|T2], Y). 

这里没有追加

+2

+1:这是一个很好的累加器版本,并会使用更少的堆栈空间作为我提出的版本(这不是尾递归)。如果使用了模式匹配,而不是在'revall/3'的第二个子句中将'H'更改为'[H | Hs]',那么您甚至可以替换'is_list/1'调用内置插件将是必要的。 – sharky 2012-04-10 23:22:14