Prolog:创建子列表,给出两个索引

时间:2013-05-07 19:32:46

标签: prolog

基本上,我需要创建表单子列表(S,M,N,L)的谓词,其中S是由索引M和索引N之间的L元素组成的新列表,包括在内。

这是我得到的地方:

sublist([],_,_,[]).
sublist([],M,N,_) :- (M > N).
sublist(S,M,N,L) :- sublist2(S,M,N,L,-1).
sublist2([H|T],St,En,[H2|T2],Idx) :-
   (Idx2 is Idx + 1,
   St =< Idx2,
   En >= Idx2,
   H = H2,
   sublist2(T,St,En,T2,Idx2);
   Idx2 is Idx + 1,
   sublist2(T,St,En,T2,Idx2)).

与我所有的prolog问题一样,我觉得我的方式比它应该更复杂。我已经确定了基本情况,但其他任何评估都是错误的。对这个问题的任何建议,以及prolog的一般方法?我在很大程度上理解这种语言,但我似乎无法看到简单的解决方案。

2 个答案:

答案 0 :(得分:1)

简单的解决方案遵循简单的前景。对于列表,它是递归。递归编程很简单 - 想象一下你已经拥有了你的函数,遵循给定的接口/要求,所以你可以随时使用它(但更好的是,在减少的情况下)。

sublist(S,M,N,[_A|B]):- M>0, M<N, sublist(S,M-1,N-1,B).

将其视为陈述一个子列表法则:较短列表中的子列表从减少的索引开始。

sublist(S,M,N,[A|B]):- 0 is M, M<N, N2 is N-1, S=[A|D], sublist(D,0,N2,B).

sublist([],0,0,_).

它在第二个索引中是独占的。调整它。 :)

答案 1 :(得分:1)

有可能以类似于更传统语言的方式处理索引:

sublist(L, M, N, S) :-
    findall(E, (nth1(I, L, E), I >= M, I =< N), S).

或等效

sublist(L, M, N, S) :-
    findall(E, (between(M, N, I), nth1(I, L, E)), S).

nth1 / 3用于从1开始索引,否则nth0 / 3允许C风格 - 从0开始。我已将子列表作为最后一个参数。 Prolog中的常见约定是在输入后放置输出参数。

这是一个(繁琐的)递归定义

sublist(L,M,N,S) :- sublist2(1,L,M,N,S).

sublist2(_,[],_,_,[]).
sublist2(I,[X|Xs],M,N,[X|Ys]) :-
    between(M,N,I),
    J is I + 1,
    !, sublist2(J,Xs,M,N,Ys).
sublist2(I,[_|Xs],M,N,Ys) :-
    J is I + 1,
    sublist2(J,Xs,M,N,Ys).