longestSubseq( List, Ans ) :-
longestSubseq( List, [], [], Ans ).
longestSubseq( [], Buffer, [], Buffer ) :- !.
longestSubseq( [], _, AnsRevert, Ans ) :-
reverse( AnsRevert, Ans ).
longestSubseq( [H | Tail], [], Longest, Ans ) :-
longestSubseq( Tail, [H], Longest, Ans ).
longestSubseq( [H | Tail], [BufHead | BufTail], Longest, Ans ) :-
BufHead =< H,
longestSubseq( Tail, [H, BufHead | BufTail], Longest, Ans ).
longestSubseq( [H | Tail], Buffer, Longest, Ans ) :-
[BufHead | _ ] = Buffer,
BufHead > H,
length( Longest, LongestLength ),
length( Buffer, BufferLength ),
(
( BufferLength > LongestLength, NewLongest = Buffer )
;
( BufferLength =< LongestLength, NewLongest = Longest )
),
longestSubseq( Tail, [H], NewLongest, Ans ).
Я не совсем знаком с gprolog, так что это код swi-prolog.
У нас есть 2 предиката: longestSubseq/2
и longestSubseq/4
.
longestSubseq/4
имеют буфер (текущая монотонная подпоследовательность), самый длинный (самая длинная подпоследовательность в текущее время) и аккумулятор Ans.
В этом аккумуляторе есть некоторые особенности поведения, которые мы должны обработать:
- Буфер пуст.Мы добавили в него новый элемент.
- Новый элемент меньше, чем последний элемент буфера.Мы помещаем этот элемент в буфер.
- Новый элемент больше, чем последний элемент буфера.Мы очищаем буфер и помещаем этот элемент в него.Если буфер был больше самой длинной подпоследовательности, мы подставляем его.
Итак, он выглядит работоспособным.
?- longestSubseq( [2], X ).
X = [2] ;
false.
?- longestSubseq( [2,1,2,3,2], X ).
X = [1, 2, 3] ;
false.