4

基本上,我需要创建一个 sublist(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)).

和我所有的序言问题一样,我觉得我让它变得比它应该的更复杂。我的基本情况是正确的,但其他任何事情的评估结果都是错误的。关于这个问题的任何建议,以及序言的一般方法?我在很大程度上理解该语言,但我似乎看不到简单的解决方案。

4

2 回答 2

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,_).

它在第二个索引中是唯一的。调整它。:)

于 2013-05-07T19:48:35.003 回答
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).
于 2013-05-07T21:10:37.200 回答