如何从Prolog中的列表中删除最后n个元素?

时间:2014-04-07 00:22:05

标签: list prolog

我想删除Prolog中列表的最后n个元素,并将其放在另一个列表中,如L2。如果我知道要删除的元素的确切数量说3,这里是代码。但我坚持变量n案例。顺便说一下,如果列表的长度小于n,我想返回一个空字符串。谢谢。

without_last_three([], []).
without_last_three([_], []).
without_last_three([_,_], []).
without_last_three([_,_,_], []).
without_last_three([Head|Tail], [Head|NTail]):-
   without_last_three(Tail, NTail).

2 个答案:

答案 0 :(得分:5)

without_last_n(Old, N, New) :-
    length(Tail, N),
    append(New, Tail, Old).

试运行:

?- without_last_n([a, b, c, d, e, f], 4, New).
New = [a, b] 

?- without_last_n([a, b, c, d, e, f], 777, New).
false.

?- without_last_n([a, b, c, d, e, f], 0, New).
New = [a, b, c, d, e, f]

更新。当N大于列表长度时,要成功[],可以添加第二个子句:

without_last_n(Old, N, []) :-
    length(Old, L),
    N > L.

答案 1 :(得分:0)

以下是一般情况:

without_last_n(L, N, []) :-
    nonvar(L), nonvar(N),
    length(L, M),
    N > M.
without_last_n(L, N, R) :-
    without_last_n_(L, N, R).

without_last_n_(L, N, []) :-
    length(L, N).
without_last_n_([H|T], N, [H|T1]) :-
    without_last_n_(T, N, T1).

这满足给定的要求,并且适用于各种变量实例化方案。如果without_last_n(L, N, []).大于N的长度,L必须成功的要求使解决方案复杂化的原因。如果这不是一个要求,那么更简单的without_last_n_/3就足以解决问题。

...测试

| ?- without_last_n([1,2,3,4], 3, R).

R = [1] ? ;

no
| ?- without_last_n([1,2,3,4], N, R).

N = 4
R = [] ? ;

N = 3
R = [1] ? ;

N = 2
R = [1,2] ? ;

N = 1
R = [1,2,3] ? ;

N = 0
R = [1,2,3,4]

(1 ms) yes
| ?- without_last_n([1,2,3,4], N, [1,2]).

N = 2 ? ;

no
| ?- without_last_n(L, 3, [1,2]).

L = [1,2,_,_,_] ? ;

no
| ?- without_last_n(L, 2, R).

L = [_,_]
R = [] ? ;

L = [A,_,_]
R = [A] ? ;

L = [A,B,_,_]
R = [A,B] ? ;

L = [A,B,C,_,_]
R = [A,B,C] ?
...
| ?- without_last_n(L, N, [1,2]).

L = [1,2]
N = 0 ? ;

L = [1,2,_]
N = 1 ? ;

L = [1,2,_,_]
N = 2 ? ;
...
| ?- without_last_n(L, N, R).

L = []
N = 0
R = [] ? ;

L = [_]
N = 1
R = [] ? ;

L = [_,_]
N = 2
R = [] ? ;

L = [_,_,_]
N = 3
R = [] ? ;
...
| ?-

这里可能存在的一个缺陷是,without_last_n([1,2,3,4], N, R).可能会生成N = 5, R = []N = 6, R = []等的解决方案 ad infinitum ,但事实并非如此。留给读者练习。 :)