Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Longest-increasing-subsequence/00-META.yaml
Normal file
2
Task/Longest-increasing-subsequence/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Longest_increasing_subsequence
|
||||
15
Task/Longest-increasing-subsequence/00-TASK.txt
Normal file
15
Task/Longest-increasing-subsequence/00-TASK.txt
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
Calculate and show here a [[wp:Longest increasing subsequence|longest increasing subsequence]] of the list:
|
||||
:<math>\{3, 2, 6, 4, 5, 1\}</math>
|
||||
And of the list:
|
||||
:<math>\{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15\}</math>
|
||||
|
||||
Note that a list may have more than one subsequence that is of the maximum length.
|
||||
|
||||
{{Template:Strings}}
|
||||
|
||||
|
||||
;Ref:
|
||||
# [http://www.youtube.com/watch?v=4fQJGoeW5VE Dynamic Programming #1: Longest Increasing Subsequence] on YouTube
|
||||
# An efficient solution can be based on [[wp:Patience sorting|Patience sorting]].
|
||||
<br><br>
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
F longest_increasing_subsequence(x)
|
||||
V n = x.len
|
||||
V P = [0] * n
|
||||
V M = [0] * (n + 1)
|
||||
V l = 0
|
||||
L(i) 0 .< n
|
||||
V lo = 1
|
||||
V hi = l
|
||||
L lo <= hi
|
||||
V mid = (lo + hi) I/ 2
|
||||
I (x[M[mid]] < x[i])
|
||||
lo = mid + 1
|
||||
E
|
||||
hi = mid - 1
|
||||
V newl = lo
|
||||
P[i] = M[newl - 1]
|
||||
M[newl] = i
|
||||
|
||||
I (newl > l)
|
||||
l = newl
|
||||
|
||||
[Int] s
|
||||
V k = M[l]
|
||||
L(i) (l - 1 .. 0).step(-1)
|
||||
s.append(x[k])
|
||||
k = P[k]
|
||||
R reversed(s)
|
||||
|
||||
L(d) [[3, 2, 6, 4, 5, 1], [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]]
|
||||
print(‘a L.I.S. of #. is #.’.format(d, longest_increasing_subsequence(d)))
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
* Longest increasing subsequence 04/03/2017
|
||||
LNGINSQ CSECT
|
||||
USING LNGINSQ,R13 base register
|
||||
B 72(R15) skip savearea
|
||||
DC 17F'0' savearea
|
||||
STM R14,R12,12(R13) save previous context
|
||||
ST R13,4(R15) link backward
|
||||
ST R15,8(R13) link forward
|
||||
LR R13,R15 set addressability
|
||||
LA R6,1 i=1
|
||||
DO WHILE=(CH,R6,LE,=H'2') do i=1 to 2
|
||||
IF CH,R6,EQ,=H'1' THEN if i=1 then
|
||||
MVC N,=AL2((A2-A1)/2) n=hbound(a1)
|
||||
MVC AA(64),A1 a=a1
|
||||
ELSE , else
|
||||
MVC N,=AL2((AA-A2)/2) n=hbound(a2)
|
||||
MVC AA(64),A2 a=a2
|
||||
ENDIF , endif
|
||||
MVC PG,=CL80': ' init buffer
|
||||
LA R2,AA-2 @a
|
||||
LH R3,N n
|
||||
BAL R14,PRINT print a
|
||||
MVC LL,=H'0' l=0
|
||||
SR R7,R7 j=0
|
||||
DO WHILE=(CH,R7,LE,N) do j=0 to n
|
||||
MVC LO,=H'1' lo=1
|
||||
MVC HI,LL hi=l
|
||||
LH R4,LO lo
|
||||
DO WHILE=(CH,R4,LE,HI) do while lo<=hi
|
||||
LH R1,LO lo
|
||||
AH R1,HI lo+hi
|
||||
SRA R1,1 /2
|
||||
STH R1,MIDDLE middle=(lo+hi)/2
|
||||
SLA R1,1 *2
|
||||
LH R1,MM(R1) m(middle+1)
|
||||
SLA R1,1 *2
|
||||
LH R3,AA(R1) r3=a(m(middle+1)+1)
|
||||
LR R1,R7 j
|
||||
SLA R1,1 *2
|
||||
LH R4,AA(R1) r4=a(j+1)
|
||||
LH R2,MIDDLE middle
|
||||
IF CR,R3,LT,R4 THEN if a(m(middle+1)+1)<a(j+1) then
|
||||
LA R2,1(R2) middle+1
|
||||
STH R2,LO lo=middle+1
|
||||
ELSE , else
|
||||
BCTR R2,0 middle-1
|
||||
STH R2,HI hi=middle-1
|
||||
ENDIF , endif
|
||||
LH R4,LO lo
|
||||
ENDDO , end /*while*/
|
||||
LH R10,LO newl=lo
|
||||
LR R1,R10 newl
|
||||
SLA R1,1 *2
|
||||
LH R3,MM-2(R1) m(newl)
|
||||
LR R1,R7 j
|
||||
SLA R1,1 *2
|
||||
STH R3,PP(R1) p(j+1)=m(newl)
|
||||
LR R1,R10 newl
|
||||
SLA R1,1 *2
|
||||
STH R7,MM(R1) m(newl+1)=j
|
||||
IF CH,R10,GT,LL if newl>l then
|
||||
STH R10,LL l=newl
|
||||
ENDIF , endif
|
||||
LA R7,1(R7) j++
|
||||
ENDDO , enddo j
|
||||
LH R1,LL l
|
||||
SLA R1,1 *2
|
||||
LH R10,MM(R1) k=m(l+1)
|
||||
LH R7,LL j=l
|
||||
DO WHILE=(CH,R7,GE,=H'1') do j=l to 1 by -1
|
||||
LR R1,R10 k
|
||||
SLA R1,1 *2
|
||||
LH R2,AA(R1) a(k+1)
|
||||
LR R1,R7 j
|
||||
SLA R1,1 *2
|
||||
STH R2,SS-2(R1) s(j)=a(k+1)
|
||||
LR R1,R10 k
|
||||
SLA R1,1 *2
|
||||
LH R10,PP(R1) k=p(k+1)
|
||||
BCTR R7,0 j--
|
||||
ENDDO , enddo j
|
||||
MVC PG,=CL80'> ' init buffer
|
||||
LA R2,SS-2 @s
|
||||
LH R3,LL l
|
||||
BAL R14,PRINT print a
|
||||
LA R6,1(R6) i++
|
||||
ENDDO , enddo i
|
||||
L R13,4(0,R13) restore previous savearea pointer
|
||||
LM R14,R12,12(R13) restore previous context
|
||||
XR R15,R15 rc=0
|
||||
BR R14 exit
|
||||
PRINT LA R10,PG ---- print subroutine
|
||||
LA R10,2(R10) pgi=2
|
||||
LA R7,1 j=1
|
||||
DO WHILE=(CR,R7,LE,R3) do j=1 to nx
|
||||
LR R1,R7 j
|
||||
SLA R1,1 *2
|
||||
LH R1,0(R2,R1) x(j)
|
||||
XDECO R1,XDEC edit x(j)
|
||||
MVC 0(3,R10),XDEC+9 output x(j)
|
||||
LA R10,3(R10) pgi+=3
|
||||
LA R7,1(R7) j++
|
||||
ENDDO , enddo j
|
||||
XPRNT PG,L'PG print buffer
|
||||
BR R14 ---- return
|
||||
A1 DC H'3',H'2',H'6',H'4',H'5',H'1'
|
||||
A2 DC H'0',H'8',H'4',H'12',H'2',H'10',H'6',H'14'
|
||||
DC H'1',H'9',H'5',H'13',H'3',H'11',H'7',H'15'
|
||||
AA DS 32H a(32)
|
||||
PP DS 32H p(32)
|
||||
MM DS 32H m(32)
|
||||
SS DS 32H s(32)
|
||||
N DS H n
|
||||
LL DS H l
|
||||
LO DS H lo
|
||||
HI DS H hi
|
||||
MIDDLE DS H middle
|
||||
PG DS CL80 buffer
|
||||
XDEC DS CL12 temp for xdeco
|
||||
YREGS
|
||||
END LNGINSQ
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
on longestIncreasingSubsequences(aList)
|
||||
script o
|
||||
property inputList : aList
|
||||
property m : {} -- End indices of identified subsequences.
|
||||
property p : {} -- 'Predecessor' indices for each point in each subsequence.
|
||||
property subsequence : {} -- Reconstructed longest sequence.
|
||||
end script
|
||||
-- Set m and p to lists of the same length as the input. Their initial contents don't matter!
|
||||
copy aList to o's m
|
||||
copy aList to o's p
|
||||
|
||||
set bestLength to 0
|
||||
repeat with i from 1 to (count o's inputList)
|
||||
-- Comments adapted from those in the Wikipedia article — as far as they can be understood!
|
||||
-- Binary search for the largest possible 'lo' ≤ bestLength such that inputList[m[lo]] ≤ inputList[i].
|
||||
set lo to 1
|
||||
set hi to bestLength
|
||||
repeat until (lo > hi)
|
||||
set mid to (lo + hi + 1) div 2
|
||||
if (item (item mid of o's m) of o's inputList < item i of o's inputList) then
|
||||
set lo to mid + 1
|
||||
else
|
||||
set hi to mid - 1
|
||||
end if
|
||||
end repeat
|
||||
-- After searching, lo is 1 greater than the length of the longest prefix of inputList[i].
|
||||
-- The predecessor of inputList[i] is the last index of the subsequence of length lo - 1.
|
||||
if (lo > 1) then set item i of o's p to item (lo - 1) of o's m
|
||||
set item lo of o's m to i
|
||||
-- If we found a subsequence longer than or the same length as any we've found yet,
|
||||
-- update bestLength and store the end index associated with it.
|
||||
if (lo > bestLength) then
|
||||
set bestLength to lo
|
||||
set bestEndIndices to {item bestLength of o's m}
|
||||
else if (lo = bestLength) then
|
||||
set end of bestEndIndices to item bestLength of o's m
|
||||
end if
|
||||
end repeat
|
||||
-- Reconstruct the longest increasing subsequence(s).
|
||||
set output to {}
|
||||
if (bestLength > 0) then
|
||||
repeat with k in bestEndIndices
|
||||
set o's subsequence to {}
|
||||
repeat bestLength times
|
||||
set beginning of o's subsequence to item k of o's inputList
|
||||
set k to item k of o's p
|
||||
end repeat
|
||||
set end of output to o's subsequence
|
||||
end repeat
|
||||
end if
|
||||
|
||||
return output
|
||||
end longestIncreasingSubsequences
|
||||
|
||||
-- Task code and other tests:
|
||||
local tests, output, input
|
||||
set tests to {{3, 2, 6, 4, 5, 1}, {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}, ¬
|
||||
{9, 10, 11, 3, 8, 9, 6, 7, 4, 5}, {4, 5, 5, 6}, {5, 5}}
|
||||
set output to {}
|
||||
repeat with input in tests
|
||||
set end of output to {finds:longestIncreasingSubsequences(input's contents)}
|
||||
end repeat
|
||||
return output
|
||||
|
|
@ -0,0 +1 @@
|
|||
{{finds:{{2, 4, 5}}}, {finds:{{0, 2, 6, 9, 11, 15}}}, {finds:{{9, 10, 11}, {3, 8, 9}, {3, 6, 7}, {3, 4, 5}}}, {finds:{{4, 5, 6}}}, {finds:{{5}, {5}}}}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
lis: function [d][
|
||||
l: new [[]]
|
||||
loop d 'num [
|
||||
x: []
|
||||
loop l 'seq [
|
||||
if positive? size seq [
|
||||
if and? num > last seq
|
||||
(size seq) > size x ->
|
||||
x: seq
|
||||
]
|
||||
]
|
||||
'l ++ @[x ++ @[num]]
|
||||
]
|
||||
result: []
|
||||
loop l 'x [
|
||||
if (size x) > size result ->
|
||||
result: x
|
||||
]
|
||||
return result
|
||||
]
|
||||
|
||||
loop [
|
||||
[3 2 6 4 5 1]
|
||||
[0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15]
|
||||
] 'seq [
|
||||
print ["LIS of" seq "=>" lis seq]
|
||||
]
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
Lists := [[3,2,6,4,5,1], [0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]]
|
||||
|
||||
for k, v in Lists {
|
||||
D := LIS(v)
|
||||
MsgBox, % D[D.I].seq
|
||||
}
|
||||
|
||||
LIS(L) {
|
||||
D := []
|
||||
for i, v in L {
|
||||
D[i, "Length"] := 1, D[i, "Seq"] := v, D[i, "Val"] := v
|
||||
Loop, % i - 1 {
|
||||
if(D[A_Index].Val < v && D[A_Index].Length + 1 > D[i].Length) {
|
||||
D[i].Length := D[A_Index].Length + 1
|
||||
D[i].Seq := D[A_Index].Seq ", " v
|
||||
if (D[i].Length > MaxLength)
|
||||
MaxLength := D[i].Length, D.I := i
|
||||
}
|
||||
}
|
||||
}
|
||||
return, D
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
#include <vector>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
template <typename T>
|
||||
struct Node {
|
||||
T value;
|
||||
Node* prev_node;
|
||||
};
|
||||
|
||||
template <typename Container>
|
||||
Container lis(const Container& values) {
|
||||
using E = typename Container::value_type;
|
||||
using NodePtr = Node<E>*;
|
||||
using ConstNodePtr = const NodePtr;
|
||||
|
||||
std::vector<NodePtr> pileTops;
|
||||
std::vector<Node<E>> nodes(values.size());
|
||||
|
||||
// sort into piles
|
||||
auto cur_node = std::begin(nodes);
|
||||
for (auto cur_value = std::begin(values); cur_value != std::end(values); ++cur_value, ++cur_node)
|
||||
{
|
||||
auto node = &*cur_node;
|
||||
node->value = *cur_value;
|
||||
|
||||
// lower_bound returns the first element that is not less than 'node->value'
|
||||
auto lb = std::lower_bound(pileTops.begin(), pileTops.end(), node,
|
||||
[](ConstNodePtr& node1, ConstNodePtr& node2) -> bool { return node1->value < node2->value; });
|
||||
|
||||
if (lb != pileTops.begin())
|
||||
node->prev_node = *std::prev(lb);
|
||||
|
||||
if (lb == pileTops.end())
|
||||
pileTops.push_back(node);
|
||||
else
|
||||
*lb = node;
|
||||
}
|
||||
|
||||
// extract LIS from piles
|
||||
// note that LIS length is equal to the number of piles
|
||||
Container result(pileTops.size());
|
||||
auto r = std::rbegin(result);
|
||||
|
||||
for (NodePtr node = pileTops.back(); node != nullptr; node = node->prev_node, ++r)
|
||||
*r = node->value;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void show_lis(const Container& values)
|
||||
{
|
||||
auto&& result = lis(values);
|
||||
for (auto& r : result) {
|
||||
std::cout << r << ' ';
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
show_lis(std::list<int> { 3, 2, 6, 4, 5, 1 });
|
||||
show_lis(std::vector<int> { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 });
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
#include <vector>
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
template <typename T>
|
||||
struct Node {
|
||||
T value;
|
||||
Node* prev_node;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool compare (const T& node1, const T& node2)
|
||||
{
|
||||
return node1->value < node2->value;
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
Container lis(const Container& values) {
|
||||
typedef typename Container::value_type E;
|
||||
typedef typename Container::const_iterator ValueConstIter;
|
||||
typedef typename Container::iterator ValueIter;
|
||||
typedef Node<E>* NodePtr;
|
||||
typedef const NodePtr ConstNodePtr;
|
||||
typedef std::vector<Node<E> > NodeVector;
|
||||
typedef std::vector<NodePtr> NodePtrVector;
|
||||
typedef typename NodeVector::iterator NodeVectorIter;
|
||||
typedef typename NodePtrVector::iterator NodePtrVectorIter;
|
||||
|
||||
std::vector<NodePtr> pileTops;
|
||||
std::vector<Node<E> > nodes(values.size());
|
||||
|
||||
// sort into piles
|
||||
NodeVectorIter cur_node = nodes.begin();
|
||||
for (ValueConstIter cur_value = values.begin(); cur_value != values.end(); ++cur_value, ++cur_node)
|
||||
{
|
||||
NodePtr node = &*cur_node;
|
||||
node->value = *cur_value;
|
||||
|
||||
// lower_bound returns the first element that is not less than 'node->value'
|
||||
NodePtrVectorIter lb = std::lower_bound(pileTops.begin(), pileTops.end(), node, compare<NodePtr>);
|
||||
|
||||
if (lb != pileTops.begin())
|
||||
node->prev_node = *(lb - 1);
|
||||
|
||||
if (lb == pileTops.end())
|
||||
pileTops.push_back(node);
|
||||
else
|
||||
*lb = node;
|
||||
}
|
||||
|
||||
// extract LIS from piles
|
||||
// note that LIS length is equal to the number of piles
|
||||
Container result(pileTops.size());
|
||||
std::reverse_iterator<ValueIter> r = std::reverse_iterator<ValueIter>(result.rbegin());
|
||||
|
||||
for (NodePtr node = pileTops.back(); node; node = node->prev_node, ++r)
|
||||
*r = node->value;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
void show_lis(const Container& values)
|
||||
{
|
||||
const Container& result = lis(values);
|
||||
for (typename Container::const_iterator it = result.begin(); it != result.end(); ++it) {
|
||||
std::cout << *it << ' ';
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const int arr1[] = { 3, 2, 6, 4, 5, 1 };
|
||||
const int arr2[] = { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
|
||||
|
||||
std::vector<int> vec1(arr1, arr1 + sizeof(arr1) / sizeof(arr1[0]));
|
||||
std::vector<int> vec2(arr2, arr2 + sizeof(arr2) / sizeof(arr2[0]));
|
||||
|
||||
show_lis(vec1);
|
||||
show_lis(vec2);
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
public static class LIS
|
||||
{
|
||||
public static IEnumerable<T> FindRec<T>(IList<T> values, IComparer<T> comparer = null) =>
|
||||
values == null ? throw new ArgumentNullException() :
|
||||
FindRecImpl(values, Sequence<T>.Empty, 0, comparer ?? Comparer<T>.Default).Reverse();
|
||||
|
||||
private static Sequence<T> FindRecImpl<T>(IList<T> values, Sequence<T> current, int index, IComparer<T> comparer) {
|
||||
if (index == values.Count) return current;
|
||||
if (current.Length > 0 && comparer.Compare(values[index], current.Value) <= 0)
|
||||
return FindRecImpl(values, current, index + 1, comparer);
|
||||
return Max(
|
||||
FindRecImpl(values, current, index + 1, comparer),
|
||||
FindRecImpl(values, current + values[index], index + 1, comparer)
|
||||
);
|
||||
}
|
||||
|
||||
private static Sequence<T> Max<T>(Sequence<T> a, Sequence<T> b) => a.Length < b.Length ? b : a;
|
||||
|
||||
class Sequence<T> : IEnumerable<T>
|
||||
{
|
||||
public static readonly Sequence<T> Empty = new Sequence<T>(default(T), null);
|
||||
|
||||
public Sequence(T value, Sequence<T> tail)
|
||||
{
|
||||
Value = value;
|
||||
Tail = tail;
|
||||
Length = tail == null ? 0 : tail.Length + 1;
|
||||
}
|
||||
|
||||
public T Value { get; }
|
||||
public Sequence<T> Tail { get; }
|
||||
public int Length { get; }
|
||||
|
||||
public static Sequence<T> operator +(Sequence<T> s, T value) => new Sequence<T>(value, s);
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
for (var s = this; s.Length > 0; s = s.Tail) yield return s.Value;
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
public static class LIS
|
||||
{
|
||||
public static T[] Find<T>(IList<T> values, IComparer<T> comparer = null) {
|
||||
if (values == null) throw new ArgumentNullException();
|
||||
if (comparer == null) comparer = Comparer<T>.Default;
|
||||
var pileTops = new List<T>();
|
||||
var pileAssignments = new int[values.Count];
|
||||
for (int i = 0; i < values.Count; i++) {
|
||||
T element = values[i];
|
||||
int pile = pileTops.BinarySearch(element, comparer);
|
||||
if (pile < 0) pile = ~pile;
|
||||
if (pile == pileTops.Count) pileTops.Add(element);
|
||||
else pileTops[pile] = element;
|
||||
pileAssignments[i] = pile;
|
||||
}
|
||||
T[] result = new T[pileTops.Count];
|
||||
for (int i = pileAssignments.Length - 1, p = pileTops.Count - 1; p >= 0; i--) {
|
||||
if (pileAssignments[i] == p) result[p--] = values[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void Main() {
|
||||
Console.WriteLine(string.Join(",", LIS.Find(new [] { 3, 2, 6, 4, 5, 1 })));
|
||||
Console.WriteLine(string.Join(",", LIS.Find(new [] { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 })));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct node {
|
||||
int val, len;
|
||||
struct node *next;
|
||||
};
|
||||
|
||||
void lis(int *v, int len)
|
||||
{
|
||||
int i;
|
||||
struct node *p, *n = calloc(len, sizeof *n);
|
||||
for (i = 0; i < len; i++)
|
||||
n[i].val = v[i];
|
||||
|
||||
for (i = len; i--; ) {
|
||||
// find longest chain that can follow n[i]
|
||||
for (p = n + i; p++ < n + len; ) {
|
||||
if (p->val > n[i].val && p->len >= n[i].len) {
|
||||
n[i].next = p;
|
||||
n[i].len = p->len + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// find longest chain
|
||||
for (i = 0, p = n; i < len; i++)
|
||||
if (n[i].len > p->len) p = n + i;
|
||||
|
||||
do printf(" %d", p->val); while ((p = p->next));
|
||||
putchar('\n');
|
||||
|
||||
free(n);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int x[] = { 3, 2, 6, 4, 5, 1 };
|
||||
int y[] = { 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15 };
|
||||
|
||||
lis(x, sizeof(x) / sizeof(int));
|
||||
lis(y, sizeof(y) / sizeof(int));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
(defn place [piles card]
|
||||
(let [[les gts] (->> piles (split-with #(<= (ffirst %) card)))
|
||||
newelem (cons card (->> les last first))
|
||||
modpile (cons newelem (first gts))]
|
||||
(concat les (cons modpile (rest gts)))))
|
||||
|
||||
(defn a-longest [cards]
|
||||
(let [piles (reduce place '() cards)]
|
||||
(->> piles last first reverse)))
|
||||
|
||||
(println (a-longest [3 2 6 4 5 1]))
|
||||
(println (a-longest [0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15]))
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
(2 4 5)
|
||||
(0 2 6 9 11 15)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
(defun longest-increasing-subseq (list)
|
||||
(let ((subseqs nil))
|
||||
(dolist (item list)
|
||||
(let ((longest-so-far (longest-list-in-lists (remove-if-not #'(lambda (l) (> item (car l))) subseqs))))
|
||||
(push (cons item longest-so-far) subseqs)))
|
||||
(reverse (longest-list-in-lists subseqs))))
|
||||
|
||||
(defun longest-list-in-lists (lists)
|
||||
(let ((longest nil)
|
||||
(longest-len 0))
|
||||
(dolist (list lists)
|
||||
(let ((len (length list)))
|
||||
(when (> len longest-len)
|
||||
(setf longest list
|
||||
longest-len len))))
|
||||
longest))
|
||||
|
||||
(dolist (l (list (list 3 2 6 4 5 1)
|
||||
(list 0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15)))
|
||||
(format t "~A~%" (longest-increasing-subseq l))))
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
(defun lis-patience-sort (input-list)
|
||||
(let ((piles nil))
|
||||
(dolist (item input-list)
|
||||
(setf piles (insert-item item piles)))
|
||||
(reverse (caar (last piles)))))
|
||||
|
||||
(defun insert-item (item piles)
|
||||
(let ((not-found t))
|
||||
(loop
|
||||
while not-found
|
||||
for pile in piles
|
||||
and prev = nil then pile
|
||||
and i from 0
|
||||
do (when (<= item (caar pile))
|
||||
(setf (elt piles i) (push (cons item (car prev)) (elt piles i))
|
||||
not-found nil)))
|
||||
(if not-found
|
||||
(append piles (list (list (cons item (caar (last piles))))))
|
||||
piles)))
|
||||
|
||||
(dolist (l (list (list 3 2 6 4 5 1)
|
||||
(list 0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15)))
|
||||
(format t "~A~%" (lis-patience-sort l)))
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
(defun insert-item (item piles)
|
||||
(multiple-value-bind
|
||||
(i prev)
|
||||
(do* ((prev nil (car x))
|
||||
(x piles (cdr x))
|
||||
(i 0 (1+ i)))
|
||||
((or (null x) (<= item (caaar x))) (values i prev)))
|
||||
(if (= i (length piles))
|
||||
(append piles (list (list (cons item (caar (last piles))))))
|
||||
(progn (push (cons item (car prev)) (elt piles i))
|
||||
piles))))
|
||||
|
||||
(defun longest-inc-seq (input)
|
||||
(do* ((piles nil (insert-item (car x) piles))
|
||||
(x input (cdr x)))
|
||||
((null x) (reverse (caar (last piles))))))
|
||||
|
||||
(dolist (l (list (list 3 2 6 4 5 1)
|
||||
(list 0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15)))
|
||||
(format t "~A~%" (longest-inc-seq l)))
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
import std.stdio, std.algorithm, power_set2;
|
||||
|
||||
T[] lis(T)(T[] items) pure nothrow {
|
||||
//return items.powerSet.filter!isSorted.max!q{ a.length };
|
||||
return items
|
||||
.powerSet
|
||||
.filter!isSorted
|
||||
.minPos!q{ a.length > b.length }
|
||||
.front;
|
||||
}
|
||||
|
||||
void main() {
|
||||
[3, 2, 6, 4, 5, 1].lis.writeln;
|
||||
[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15].lis.writeln;
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
import std.stdio, std.algorithm, std.array;
|
||||
|
||||
/// Return one of the Longest Increasing Subsequence of
|
||||
/// items using patience sorting.
|
||||
T[] lis(T)(in T[] items) pure nothrow
|
||||
if (__traits(compiles, T.init < T.init))
|
||||
out(result) {
|
||||
assert(result.length <= items.length);
|
||||
assert(result.isSorted);
|
||||
assert(result.all!(x => items.canFind(x)));
|
||||
} body {
|
||||
if (items.empty)
|
||||
return null;
|
||||
|
||||
static struct Node { T val; Node* back; }
|
||||
auto pile = [[new Node(items[0])]];
|
||||
|
||||
OUTER: foreach (immutable di; items[1 .. $]) {
|
||||
foreach (immutable j, ref pj; pile)
|
||||
if (pj[$ - 1].val > di) {
|
||||
pj ~= new Node(di, j ? pile[j - 1][$ - 1] : null);
|
||||
continue OUTER;
|
||||
}
|
||||
pile ~= [new Node(di, pile[$ - 1][$ - 1])];
|
||||
}
|
||||
|
||||
T[] result;
|
||||
for (auto ptr = pile[$ - 1][$ - 1]; ptr != null; ptr = ptr.back)
|
||||
result ~= ptr.val;
|
||||
result.reverse();
|
||||
return result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
foreach (d; [[3,2,6,4,5,1],
|
||||
[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]])
|
||||
d.lis.writeln;
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import std.stdio, std.algorithm, std.range, std.array;
|
||||
|
||||
T[] lis(T)(in T[] items) pure nothrow
|
||||
if (__traits(compiles, T.init < T.init))
|
||||
out(result) {
|
||||
assert(result.length <= items.length);
|
||||
assert(result.isSorted);
|
||||
assert(result.all!(x => items.canFind(x)));
|
||||
} body {
|
||||
if (items.empty)
|
||||
return null;
|
||||
|
||||
static struct Node {
|
||||
T value;
|
||||
Node* pointer;
|
||||
}
|
||||
Node*[] pileTops;
|
||||
auto nodes = minimallyInitializedArray!(Node[])(items.length);
|
||||
|
||||
// Sort into piles.
|
||||
foreach (idx, x; items) {
|
||||
auto node = &nodes[idx];
|
||||
node.value = x;
|
||||
immutable i = pileTops.length -
|
||||
pileTops.assumeSorted!q{a.value < b.value}
|
||||
.upperBound(node)
|
||||
.length;
|
||||
if (i != 0)
|
||||
node.pointer = pileTops[i - 1];
|
||||
if (i != pileTops.length)
|
||||
pileTops[i] = node;
|
||||
else
|
||||
pileTops ~= node;
|
||||
}
|
||||
|
||||
// Extract LIS from nodes.
|
||||
size_t count = 0;
|
||||
for (auto n = pileTops[$ - 1]; n != null; n = n.pointer)
|
||||
count++;
|
||||
auto result = minimallyInitializedArray!(T[])(count);
|
||||
for (auto n = pileTops[$ - 1]; n != null; n = n.pointer)
|
||||
result[--count] = n.value;
|
||||
return result;
|
||||
}
|
||||
|
||||
void main() {
|
||||
foreach (d; [[3,2,6,4,5,1],
|
||||
[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]])
|
||||
d.writeln;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
defmodule Longest_increasing_subsequence do
|
||||
# Naive implementation
|
||||
def lis(l) do
|
||||
(for ss <- combos(l), ss == Enum.sort(ss), do: ss)
|
||||
|> Enum.max_by(fn ss -> length(ss) end)
|
||||
end
|
||||
|
||||
defp combos(l) do
|
||||
Enum.reduce(1..length(l), [[]], fn k, acc -> acc ++ (combos(k, l)) end)
|
||||
end
|
||||
defp combos(1, l), do: (for x <- l, do: [x])
|
||||
defp combos(k, l) when k == length(l), do: [l]
|
||||
defp combos(k, [h|t]) do
|
||||
(for subcombos <- combos(k-1, t), do: [h | subcombos]) ++ combos(k, t)
|
||||
end
|
||||
end
|
||||
|
||||
IO.inspect Longest_increasing_subsequence.lis([3,2,6,4,5,1])
|
||||
IO.inspect Longest_increasing_subsequence.lis([0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15])
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
defmodule Longest_increasing_subsequence do
|
||||
# Patience sort implementation
|
||||
def patience_lis(l), do: patience_lis(l, [])
|
||||
|
||||
defp patience_lis([h | t], []), do: patience_lis(t, [[{h,[]}]])
|
||||
defp patience_lis([h | t], stacks), do: patience_lis(t, place_in_stack(h, stacks, []))
|
||||
defp patience_lis([], []), do: []
|
||||
defp patience_lis([], stacks), do: get_previous(stacks) |> recover_lis |> Enum.reverse
|
||||
|
||||
defp place_in_stack(e, [stack = [{h,_} | _] | tstacks], prevstacks) when h > e do
|
||||
prevstacks ++ [[{e, get_previous(prevstacks)} | stack] | tstacks]
|
||||
end
|
||||
defp place_in_stack(e, [stack | tstacks], prevstacks) do
|
||||
place_in_stack(e, tstacks, prevstacks ++ [stack])
|
||||
end
|
||||
defp place_in_stack(e, [], prevstacks) do
|
||||
prevstacks ++ [[{e, get_previous(prevstacks)}]]
|
||||
end
|
||||
|
||||
defp get_previous(stack = [_|_]), do: hd(List.last(stack))
|
||||
defp get_previous([]), do: []
|
||||
|
||||
defp recover_lis({e, prev}), do: [e | recover_lis(prev)]
|
||||
defp recover_lis([]), do: []
|
||||
end
|
||||
|
||||
IO.inspect Longest_increasing_subsequence.patience_lis([3,2,6,4,5,1])
|
||||
IO.inspect Longest_increasing_subsequence.patience_lis([0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15])
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
-module(longest_increasing_subsequence).
|
||||
|
||||
-export([test_naive/0, test_memo/0, test_patience/0, test_patience2/0, test_compare/1]).
|
||||
|
||||
% **************************************************
|
||||
% Interface to test the implementation
|
||||
% **************************************************
|
||||
|
||||
test_compare(N) when N =< 20 ->
|
||||
Funs = [
|
||||
{"Naive", fun lis/1},
|
||||
{"Memo", fun memo/1},
|
||||
{"Patience", fun patience_lis/1},
|
||||
{"Patience2", fun patience2/1}
|
||||
],
|
||||
do_compare(Funs, N);
|
||||
test_compare(N) when N =< 500 ->
|
||||
Funs = [
|
||||
{"Memo", fun memo/1},
|
||||
{"Patience", fun patience_lis/1},
|
||||
{"Patience2", fun patience2/1}
|
||||
],
|
||||
do_compare(Funs, N);
|
||||
test_compare(N) ->
|
||||
Funs = [
|
||||
{"Patience", fun patience_lis/1},
|
||||
{"Patience2", fun patience2/1}
|
||||
],
|
||||
do_compare(Funs, N).
|
||||
|
||||
do_compare(Funs, N) ->
|
||||
List = [rand:uniform(1000) || _ <- lists:seq(1,N)],
|
||||
Results = [{Name, timer:tc(fun() -> F(List) end)} || {Name,F} <- Funs],
|
||||
Times = [{Name, Time} || {Name, {Time, _Result}} <- Results],
|
||||
io:format("Result Times: ~p~n", [Times]).
|
||||
|
||||
test_naive() ->
|
||||
test_gen(fun lis/1).
|
||||
|
||||
test_memo() ->
|
||||
test_gen(fun memo/1).
|
||||
|
||||
test_patience() ->
|
||||
test_gen(fun patience_lis/1).
|
||||
|
||||
test_patience2() ->
|
||||
test_gen(fun patience2/1).
|
||||
|
||||
test_gen(F) ->
|
||||
show_result(F([3,2,6,4,5,1])),
|
||||
show_result(F([0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15])).
|
||||
|
||||
show_result(Res) ->
|
||||
io:format("~w\n", [Res]).
|
||||
|
||||
% **************************************************
|
||||
|
||||
% **************************************************
|
||||
% Naive implementation
|
||||
% **************************************************
|
||||
|
||||
lis(L) ->
|
||||
maxBy(
|
||||
fun(SS) -> length(SS) end,
|
||||
[ lists:usort(SS)
|
||||
|| SS <- combos(L),
|
||||
SS == lists:sort(SS)]
|
||||
).
|
||||
|
||||
|
||||
% **************************************************
|
||||
% Copied from http://stackoverflow.com/a/4762387/4162959
|
||||
% **************************************************
|
||||
|
||||
maxBy(F, L) ->
|
||||
element(
|
||||
2,
|
||||
lists:max([ {F(X), X} || X <- L])
|
||||
).
|
||||
|
||||
% **************************************************
|
||||
% Copied from https://panduwana.wordpress.com/2010/04/21/combination-in-erlang/
|
||||
% **************************************************
|
||||
|
||||
combos(L) ->
|
||||
lists:foldl(
|
||||
fun(K, Acc) -> Acc++(combos(K, L)) end,
|
||||
[[]],
|
||||
lists:seq(1, length(L))
|
||||
).
|
||||
|
||||
combos(1, L) ->
|
||||
[[X] || X <- L];
|
||||
combos(K, L) when K == length(L) ->
|
||||
[L];
|
||||
combos(K, [H|T]) ->
|
||||
[[H | Subcombos]
|
||||
|| Subcombos <- combos(K-1, T)]
|
||||
++ (combos(K, T)).
|
||||
% **************************************************
|
||||
|
||||
% **************************************************
|
||||
% Memoization implementation, Roman Rabinovich
|
||||
% **************************************************
|
||||
memo(S) ->
|
||||
put(test, #{}),
|
||||
memo(S, -1).
|
||||
|
||||
memo([], _) -> [];
|
||||
memo([H | Tail] = S, Min) when H > Min ->
|
||||
case maps:get({S,Min}, get(test), undefined) of
|
||||
undefined ->
|
||||
L1 = [H | memo(Tail, H)],
|
||||
L2 = memo(Tail, Min),
|
||||
case length(L1) >= length(L2) of
|
||||
true ->
|
||||
Map = get(test),
|
||||
put(test, Map#{{S, Min} => L1}),
|
||||
L1;
|
||||
_ ->
|
||||
Map = get(test),
|
||||
put(test, Map#{{S, Min} => L2}),
|
||||
L2
|
||||
end;
|
||||
X -> X
|
||||
end;
|
||||
memo([_|Tail], Min) ->
|
||||
memo(Tail, Min).
|
||||
|
||||
% **************************************************
|
||||
|
||||
% **************************************************
|
||||
% Patience sort implementation
|
||||
% **************************************************
|
||||
|
||||
patience_lis(L) ->
|
||||
patience_lis(L, []).
|
||||
|
||||
patience_lis([H | T], Stacks) ->
|
||||
NStacks =
|
||||
case Stacks of
|
||||
[] ->
|
||||
[[{H,[]}]];
|
||||
_ ->
|
||||
place_in_stack(H, Stacks, [])
|
||||
end,
|
||||
patience_lis(T, NStacks);
|
||||
patience_lis([], Stacks) ->
|
||||
case Stacks of
|
||||
[] ->
|
||||
[];
|
||||
[_|_] ->
|
||||
lists:reverse( recover_lis( get_previous(Stacks) ) )
|
||||
end.
|
||||
|
||||
place_in_stack(E, [Stack = [{H,_} | _] | TStacks], PrevStacks) when H > E ->
|
||||
PrevStacks ++ [[{E, get_previous(PrevStacks)} | Stack] | TStacks];
|
||||
place_in_stack(E, [Stack = [{H,_} | _] | TStacks], PrevStacks) when H =< E ->
|
||||
place_in_stack(E, TStacks, PrevStacks ++ [Stack]);
|
||||
place_in_stack(E, [], PrevStacks)->
|
||||
PrevStacks ++ [[{E, get_previous(PrevStacks)}]].
|
||||
|
||||
get_previous(Stack = [_|_]) ->
|
||||
hd(lists:last(Stack));
|
||||
get_previous([]) ->
|
||||
[].
|
||||
|
||||
recover_lis({E,Prev}) ->
|
||||
[E|recover_lis(Prev)];
|
||||
recover_lis([]) ->
|
||||
[].
|
||||
|
||||
% **************************************************
|
||||
|
||||
% **************************************************
|
||||
% Patience2 by Roman Rabinovich, improved performance over above
|
||||
% **************************************************
|
||||
patience2([]) -> [];
|
||||
patience2([H|L]) ->
|
||||
Piles = [[{H, undefined}]],
|
||||
patience2(L, Piles, []).
|
||||
|
||||
patience2([], Piles, _) ->
|
||||
get_seq(lists:reverse(Piles));
|
||||
|
||||
patience2([H|T], [[{PE,_}|_Rest] = Pile| Piles], PrevPiles) when H =< PE ->
|
||||
case PrevPiles of
|
||||
[] -> patience2(T, [[{H, undefined}|Pile]|Piles], []);
|
||||
[[{K,_}|_]|_] -> patience2(T, lists:reverse(PrevPiles) ++ [[{H, K}|Pile]|Piles], [])
|
||||
end;
|
||||
|
||||
patience2([H|_T] = L, [[{PE,_}|_Rest] = Pile| Piles], PrevPiles) when H > PE ->
|
||||
patience2(L, Piles, [Pile|PrevPiles]);
|
||||
|
||||
patience2([H|T], [], [[{K,_}|_]|_]=PrevPiles) ->
|
||||
patience2(T, lists:reverse([[{H,K}]|PrevPiles]), []).
|
||||
|
||||
get_seq([]) -> [];
|
||||
get_seq([[{K,P}|_]|Rest]) ->
|
||||
get_seq(P, Rest, [K]).
|
||||
|
||||
get_seq(undefined, [], Seq) -> Seq;
|
||||
get_seq(K, [Pile|Rest], Seq) ->
|
||||
case lists:keyfind(K, 1, Pile) of
|
||||
undefined -> get_seq(K, Rest, Seq);
|
||||
{K, P} -> get_seq(P, Rest, [K|Seq])
|
||||
end.
|
||||
|
||||
% **************************************************
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
Sub Lis(arr() As Integer)
|
||||
Dim As Integer lb = Lbound(arr), ub = Ubound(arr)
|
||||
Dim As Integer i, lo, hi, mitad, newl, l = 0
|
||||
Dim As Integer p(ub), m(ub)
|
||||
|
||||
For i = lb To ub
|
||||
lo = 1
|
||||
hi = l
|
||||
Do While lo <= hi
|
||||
mitad = Int((lo+hi)/2)
|
||||
If arr(m(mitad)) < arr(i) Then
|
||||
lo = mitad + 1
|
||||
Else
|
||||
hi = mitad - 1
|
||||
End If
|
||||
Loop
|
||||
newl = lo
|
||||
p(i) = m(newl-1)
|
||||
m(newl) = i
|
||||
If newL > l Then l = newl
|
||||
Next i
|
||||
|
||||
Dim As Integer res(l)
|
||||
Dim As Integer k = m(l)
|
||||
For i = l-1 To 0 Step - 1
|
||||
res(i) = arr(k)
|
||||
k = p(k)
|
||||
Next i
|
||||
|
||||
For i = Lbound(res) To Ubound(res)-1
|
||||
Print res(i); " ";
|
||||
Next i
|
||||
End Sub
|
||||
|
||||
Dim As Integer arrA(5) => {3,2,6,4,5,1}
|
||||
Lis(arrA())
|
||||
Print
|
||||
Dim As Integer arrB(15) => {0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}
|
||||
Lis(arrB())
|
||||
|
||||
Sleep
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
type Node struct {
|
||||
val int
|
||||
back *Node
|
||||
}
|
||||
|
||||
func lis (n []int) (result []int) {
|
||||
var pileTops []*Node
|
||||
// sort into piles
|
||||
for _, x := range n {
|
||||
j := sort.Search(len(pileTops), func (i int) bool { return pileTops[i].val >= x })
|
||||
node := &Node{ x, nil }
|
||||
if j != 0 { node.back = pileTops[j-1] }
|
||||
if j != len(pileTops) {
|
||||
pileTops[j] = node
|
||||
} else {
|
||||
pileTops = append(pileTops, node)
|
||||
}
|
||||
}
|
||||
|
||||
if len(pileTops) == 0 { return []int{} }
|
||||
for node := pileTops[len(pileTops)-1]; node != nil; node = node.back {
|
||||
result = append(result, node.val)
|
||||
}
|
||||
// reverse
|
||||
for i := 0; i < len(result)/2; i++ {
|
||||
result[i], result[len(result)-i-1] = result[len(result)-i-1], result[i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
for _, d := range [][]int{{3, 2, 6, 4, 5, 1},
|
||||
{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}} {
|
||||
fmt.Printf("an L.I.S. of %v is %v\n", d, lis(d))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import Data.Ord ( comparing )
|
||||
import Data.List ( maximumBy, subsequences )
|
||||
import Data.List.Ordered ( isSorted, nub )
|
||||
|
||||
lis :: Ord a => [a] -> [a]
|
||||
lis = maximumBy (comparing length) . map nub . filter isSorted . subsequences
|
||||
-- longest <-- unique <-- increasing <-- all
|
||||
|
||||
main = do
|
||||
print $ lis [3,2,6,4,5,1]
|
||||
print $ lis [0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]
|
||||
print $ lis [1,1,1,1]
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
{-# LANGUAGE FlexibleContexts, UnicodeSyntax #-}
|
||||
|
||||
module Main (main, lis) where
|
||||
|
||||
import Control.Monad.ST ( ST, runST )
|
||||
import Control.Monad ( (>>=), (=<<), foldM )
|
||||
import Data.Array.ST ( Ix, STArray, readArray, writeArray, newArray )
|
||||
import Data.Array.MArray ( MArray )
|
||||
|
||||
infix 4 ≡
|
||||
|
||||
(≡) :: Eq α ⇒ α → α → Bool
|
||||
(≡) = (==)
|
||||
|
||||
(∘) = (.)
|
||||
|
||||
|
||||
lis ∷ Ord α ⇒ [α] → [α]
|
||||
lis xs = runST $ do
|
||||
let lxs = length xs
|
||||
pileTops ← newSTArray (min 1 lxs , lxs) []
|
||||
i ← foldM (stack pileTops) 0 xs
|
||||
readArray pileTops i >>= return ∘ reverse
|
||||
|
||||
stack ∷ (Integral ι, Ord ε, Ix ι, MArray α [ε] μ)
|
||||
⇒ α ι [ε] → ι → ε → μ ι
|
||||
stack piles i x = do
|
||||
j ← bsearch piles x i
|
||||
writeArray piles j ∘ (x:) =<< if j ≡ 1 then return []
|
||||
else readArray piles (j-1)
|
||||
return $ if j ≡ i+1 then i+1 else i
|
||||
|
||||
bsearch ∷ (Integral ι, Ord ε, Ix ι, MArray α [ε] μ)
|
||||
⇒ α ι [ε] → ε → ι → μ ι
|
||||
bsearch piles x = go 1
|
||||
where go lo hi | lo > hi = return lo
|
||||
| otherwise =
|
||||
do (y:_) ← readArray piles mid
|
||||
if y < x then go (succ mid) hi
|
||||
else go lo (pred mid)
|
||||
|
||||
where mid = (lo + hi) `div` 2
|
||||
|
||||
newSTArray ∷ Ix ι ⇒ (ι,ι) → ε → ST σ (STArray σ ι ε)
|
||||
newSTArray = newArray
|
||||
|
||||
|
||||
main ∷ IO ()
|
||||
main = do
|
||||
print $ lis [3, 2, 6, 4, 5, 1]
|
||||
print $ lis [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]
|
||||
print $ lis [1, 1, 1, 1]
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
procedure main(A)
|
||||
every writes((!lis(A)||" ") | "\n")
|
||||
end
|
||||
|
||||
procedure lis(A)
|
||||
r := [A[1]] | fail
|
||||
every (put(pt := [], [v := !A]), p := !pt) do
|
||||
if put(p, p[-1] < v) then r := (*p > *r, p)
|
||||
else p[-1] := (p[-2] < v)
|
||||
return r
|
||||
end
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
increasing=: (-: /:~)@#~"1 #:@i.@^~&2@#
|
||||
longestinc=: ] #~ [: (#~ ([: (= >./) +/"1)) #:@I.@increasing
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
longestinc 3,2,6,4,5,1
|
||||
2 4 5
|
||||
3 4 5
|
||||
longestinc 0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15
|
||||
0 2 6 9 11 15
|
||||
0 2 6 9 13 15
|
||||
0 4 6 9 11 15
|
||||
0 4 6 9 13 15
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
import java.util.*;
|
||||
|
||||
public class LIS {
|
||||
public static <E extends Comparable<? super E>> List<E> lis(List<E> n) {
|
||||
List<Node<E>> pileTops = new ArrayList<Node<E>>();
|
||||
// sort into piles
|
||||
for (E x : n) {
|
||||
Node<E> node = new Node<E>();
|
||||
node.value = x;
|
||||
int i = Collections.binarySearch(pileTops, node);
|
||||
if (i < 0) i = ~i;
|
||||
if (i != 0)
|
||||
node.pointer = pileTops.get(i-1);
|
||||
if (i != pileTops.size())
|
||||
pileTops.set(i, node);
|
||||
else
|
||||
pileTops.add(node);
|
||||
}
|
||||
// extract LIS from nodes
|
||||
List<E> result = new ArrayList<E>();
|
||||
for (Node<E> node = pileTops.size() == 0 ? null : pileTops.get(pileTops.size()-1);
|
||||
node != null; node = node.pointer)
|
||||
result.add(node.value);
|
||||
Collections.reverse(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class Node<E extends Comparable<? super E>> implements Comparable<Node<E>> {
|
||||
public E value;
|
||||
public Node<E> pointer;
|
||||
public int compareTo(Node<E> y) { return value.compareTo(y.value); }
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<Integer> d = Arrays.asList(3,2,6,4,5,1);
|
||||
System.out.printf("an L.I.S. of %s is %s\n", d, lis(d));
|
||||
d = Arrays.asList(0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15);
|
||||
System.out.printf("an L.I.S. of %s is %s\n", d, lis(d));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
function getLis(input) {
|
||||
if (input.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var lisLenPerIndex = [];
|
||||
let max = { index: 0, length: 1 };
|
||||
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
lisLenPerIndex[i] = 1;
|
||||
for (var j = i - 1; j >= 0; j--) {
|
||||
if (input[i] > input[j] && lisLenPerIndex[j] >= lisLenPerIndex[i]) {
|
||||
var length = lisLenPerIndex[i] = lisLenPerIndex[j] + 1;
|
||||
if (length > max.length) {
|
||||
max = { index: i, length };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var lis = [input[max.index]];
|
||||
for (var i = max.index; i >= 0 && max.length !== 0; i--) {
|
||||
if (input[max.index] > input[i] && lisLenPerIndex[i] === max.length - 1) {
|
||||
lis.unshift(input[i]);
|
||||
max.length--;
|
||||
}
|
||||
}
|
||||
|
||||
return lis;
|
||||
}
|
||||
|
||||
console.log(getLongestIncreasingSubsequence([0, 7, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]));
|
||||
console.log(getLongestIncreasingSubsequence([3, 2, 6, 4, 5, 1]));
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
function getLIS(input) {
|
||||
if (input.length === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const piles = [input[0]];
|
||||
|
||||
for (let i = 1; i < input.length; i++) {
|
||||
const leftPileIdx = binarySearch(piles, input[i]);
|
||||
|
||||
if (leftPileIdx !== -1) {
|
||||
piles[leftPileIdx] = input[i];
|
||||
} else {
|
||||
piles.push(input[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return piles.length;
|
||||
}
|
||||
|
||||
function binarySearch(arr, target) {
|
||||
let lo = 0;
|
||||
let hi = arr.length - 1;
|
||||
|
||||
while (lo <= hi) {
|
||||
const mid = lo + Math.floor((hi - lo) / 2);
|
||||
|
||||
if (arr[mid] >= target) {
|
||||
hi = mid - 1;
|
||||
} else {
|
||||
lo = mid + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return lo < arr.length ? lo : -1;
|
||||
}
|
||||
|
||||
console.log(getLongestIncreasingSubsequence([0, 7, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]));
|
||||
console.log(getLongestIncreasingSubsequence([3, 2, 6, 4, 5, 1]));
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
def until(cond; update):
|
||||
def _until:
|
||||
if cond then . else (update | _until) end;
|
||||
try _until catch if .== "break" then empty else . end;
|
||||
|
||||
# binary search for insertion point
|
||||
def bsearch(target):
|
||||
. as $in
|
||||
| [0, length-1] # [low, high]
|
||||
| until(.[0] > .[1];
|
||||
.[0] as $low | .[1] as $high
|
||||
| ($low + ($high - $low) / 2 | floor) as $mid
|
||||
| if $in[$mid] >= target
|
||||
then .[1] = $mid - 1
|
||||
else .[0] = $mid + 1
|
||||
end )
|
||||
| .[0];
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
def lis:
|
||||
|
||||
# Helper function:
|
||||
# given a stream, produce an array of the items in reverse order:
|
||||
def reverse(stream): reduce stream as $i ([]; [$i] + .);
|
||||
|
||||
# put the items into increasing piles using the structure:
|
||||
# NODE = {"val": value, "back": NODE}
|
||||
reduce .[] as $x
|
||||
( []; # array of NODE
|
||||
# binary search for the appropriate pile
|
||||
(map(.val) | bsearch($x)) as $i
|
||||
| setpath([$i];
|
||||
{"val": $x,
|
||||
"back": (if $i > 0 then .[$i-1] else null end) })
|
||||
)
|
||||
| .[length - 1]
|
||||
| reverse( recurse(.back) | .val ) ;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
( [3,2,6,4,5,1],
|
||||
[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]
|
||||
) | lis
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
$ jq -c -n -f lis.jq
|
||||
[2,4,5]
|
||||
[0,2,6,9,11,15]
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
function lis(arr::Vector)
|
||||
if length(arr) == 0 return copy(arr) end
|
||||
L = Vector{typeof(arr)}(length(arr))
|
||||
L[1] = [arr[1]]
|
||||
|
||||
for i in 2:length(arr)
|
||||
nextL = []
|
||||
for j in 1:i
|
||||
if arr[j] < arr[i] && length(L[j]) ≥ length(nextL)
|
||||
nextL = L[j]
|
||||
end
|
||||
end
|
||||
L[i] = vcat(nextL, arr[i])
|
||||
end
|
||||
|
||||
return L[indmax(length.(L))]
|
||||
end
|
||||
|
||||
@show lis([3, 2, 6, 4, 5, 1])
|
||||
@show lis([0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15])
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// version 1.1.0
|
||||
|
||||
fun longestIncreasingSubsequence(x: IntArray): IntArray =
|
||||
when (x.size) {
|
||||
0 -> IntArray(0)
|
||||
1 -> x
|
||||
else -> {
|
||||
val n = x.size
|
||||
val p = IntArray(n)
|
||||
val m = IntArray(n + 1)
|
||||
var len = 0
|
||||
for (i in 0 until n) {
|
||||
var lo = 1
|
||||
var hi = len
|
||||
while (lo <= hi) {
|
||||
val mid = Math.ceil((lo + hi) / 2.0).toInt()
|
||||
if (x[m[mid]] < x[i]) lo = mid + 1
|
||||
else hi = mid - 1
|
||||
}
|
||||
val newLen = lo
|
||||
p[i] = m[newLen - 1]
|
||||
m[newLen] = i
|
||||
if (newLen > len) len = newLen
|
||||
}
|
||||
val s = IntArray(len)
|
||||
var k = m[len]
|
||||
for (i in len - 1 downTo 0) {
|
||||
s[i] = x[k]
|
||||
k = p[k]
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val lists = listOf(
|
||||
intArrayOf(3, 2, 6, 4, 5, 1),
|
||||
intArrayOf(0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15)
|
||||
)
|
||||
lists.forEach { println(longestIncreasingSubsequence(it).asList()) }
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
function buildLIS(seq)
|
||||
local piles = { { {table.remove(seq, 1), nil} } }
|
||||
while #seq>0 do
|
||||
local x=table.remove(seq, 1)
|
||||
for j=1,#piles do
|
||||
if piles[j][#piles[j]][1]>x then
|
||||
table.insert(piles[j], {x, (piles[j-1] and #piles[j-1])})
|
||||
break
|
||||
elseif j==#piles then
|
||||
table.insert(piles, {{x, #piles[j]}})
|
||||
end
|
||||
end
|
||||
end
|
||||
local t={}
|
||||
table.insert(t, piles[#piles][1][1])
|
||||
local p=piles[#piles][1][2]
|
||||
for i=#piles-1,1,-1 do
|
||||
table.insert(t, piles[i][p][1])
|
||||
p=piles[i][p][2]
|
||||
end
|
||||
table.sort(t)
|
||||
print(unpack(t))
|
||||
end
|
||||
|
||||
buildLIS({3,2,6,4,5,1})
|
||||
buildLIS({0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15})
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
Module LIS_example {
|
||||
Function LIS {
|
||||
LD=Stack.Size-1
|
||||
dim L(0 to LD)
|
||||
For i=0 to LD : Read V: L(i):=Stack:=V:next
|
||||
M=1
|
||||
M1=LD
|
||||
for i=LD-1 to 0
|
||||
for j=LD to i+1
|
||||
if stackitem(L(i))<stackitem(L(j)) then
|
||||
if len(L(i))<=len(L(j)) then L(i) =stack:=stackitem(L(i)), ! stack(L(j))
|
||||
end if
|
||||
next
|
||||
if len(L(i))>=M then M1=i:M=Len(L(i))
|
||||
next
|
||||
=L(M1)
|
||||
}
|
||||
Const seq$="sequence", subseq$="Longest increasing subsequence"
|
||||
Document doc$
|
||||
Disp(seq$, Stack:=3,2,6,4,5,1)
|
||||
Disp(subseq$, Lis(3,2,6,4,5,1))
|
||||
Disp(seq$, Stack:=0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15)
|
||||
Disp(subseq$, LIS(0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15))
|
||||
Print #-2,Doc$
|
||||
Clipboard Doc$
|
||||
|
||||
Sub Disp(title$, m)
|
||||
local n=each(m), s$
|
||||
while n
|
||||
s$+=", "+str$(stackitem(n),"")
|
||||
end while
|
||||
s$=trim$(mid$(s$, 2))
|
||||
Doc$=title$+": "+s$+{
|
||||
}
|
||||
End Sub
|
||||
}
|
||||
LIS_example
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
Module LIS_example {
|
||||
Function LIS {
|
||||
LD=Stack.Size-1
|
||||
dim L(0 to LD)
|
||||
For i=0 to LD : Read V: L(i):=(V,):next
|
||||
M=1
|
||||
M1=LD
|
||||
for i=LD-1 to 0
|
||||
for j=LD to i+1
|
||||
if Array(L(i))<Array(L(j)) then
|
||||
' you can use either is the same
|
||||
' if len(L(i))<=len(L(j)) then L(i)=Cons((Array(L(i)),), L(j))
|
||||
if len(L(i))<=len(L(j)) then L(i)=(Array(L(i)),): Append L(i), L(j)
|
||||
end if
|
||||
next
|
||||
if len(L(i))>=M then M1=i:M=Len(L(i))
|
||||
next
|
||||
=L(M1)
|
||||
}
|
||||
Const seq$="sequence", subseq$="Longest increasing subsequence"
|
||||
Document doc$
|
||||
Disp(seq$, (3,2,6,4,5,1))
|
||||
Disp(subseq$, LIS(3,2,6,4,5,1))
|
||||
Disp(seq$, (0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15))
|
||||
Disp(subseq$, LIS(0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15))
|
||||
Print #-2,Doc$
|
||||
Clipboard Doc$
|
||||
|
||||
Sub Disp(title$, m)
|
||||
local n=each(m), s$
|
||||
while n
|
||||
s$+=", "+str$(Array(n),"")
|
||||
end while
|
||||
s$=trim$(mid$(s$, 2))
|
||||
Doc$=title$+": "+s$+{
|
||||
}
|
||||
End Sub
|
||||
}
|
||||
LIS_example
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# dynamic programming:
|
||||
LIS := proc(L)
|
||||
local i, j;
|
||||
local index := 1;
|
||||
local output := Array(1..numelems(L), i -> Array(1..0));
|
||||
|
||||
for i from 1 to numelems(L) do
|
||||
for j from 1 to i - 1 do
|
||||
if (L[j] < L[i]) and (upperbound(output[j]) > upperbound(output[i])) then
|
||||
output[i] := copy(output[j]);
|
||||
end if;
|
||||
end do;
|
||||
# append current value
|
||||
output[i] ,= L[i];
|
||||
end do;
|
||||
|
||||
#output longest subsequence using loop
|
||||
for i from 2 to numelems(L) do
|
||||
if (upperbound(output[i]) > upperbound(output[index])) then
|
||||
index := i;
|
||||
end if;
|
||||
end do;
|
||||
|
||||
return output[index];
|
||||
|
||||
end proc:
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
i := max[index](map(numelems,output));
|
||||
output[i];
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
L := [3, 2, 6, 4, 5, 1];
|
||||
M := [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15];
|
||||
LIS(L);
|
||||
LIS(M);
|
||||
|
|
@ -0,0 +1 @@
|
|||
LongestAscendingSequence/@{{3,2,6,4,5,1},{0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15}}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
proc longestIncreasingSubsequence[T](d: seq[T]): seq[T] =
|
||||
var l: seq[seq[T]]
|
||||
for i in 0 .. d.high:
|
||||
var x: seq[T]
|
||||
for j in 0 ..< i:
|
||||
if l[j][l[j].high] < d[i] and l[j].len > x.len:
|
||||
x = l[j]
|
||||
l.add x & @[d[i]]
|
||||
for x in l:
|
||||
if x.len > result.len:
|
||||
result = x
|
||||
|
||||
for d in [@[3,2,6,4,5,1], @[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]]:
|
||||
echo "A L.I.S. of ", d, " is ", longestIncreasingSubsequence(d)
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
let longest l = List.fold_left (fun acc x -> if List.length acc < List.length x
|
||||
then x
|
||||
else acc) [] l
|
||||
|
||||
let subsequences d l =
|
||||
let rec check_subsequences acc = function
|
||||
| x::s -> check_subsequences (if (List.hd (List.rev x)) < d
|
||||
then x::acc
|
||||
else acc) s
|
||||
| [] -> acc
|
||||
in check_subsequences [] l
|
||||
|
||||
let lis d =
|
||||
let rec lis' l = function
|
||||
| x::s -> lis' ((longest (subsequences x l)@[x])::l) s
|
||||
| [] -> longest l
|
||||
in lis' [] d
|
||||
|
||||
let _ =
|
||||
let sequences = [[3; 2; 6; 4; 5; 1]; [0; 8; 4; 12; 2; 10; 6; 14; 1; 9; 5; 13; 3; 11; 7; 15]]
|
||||
in
|
||||
List.map (fun x -> print_endline (String.concat " " (List.map string_of_int
|
||||
(lis x)))) sequences
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
let lis cmp list =
|
||||
let pile_tops = Array.make (List.length list) [] in
|
||||
let bsearch_piles x len =
|
||||
let rec aux lo hi =
|
||||
if lo > hi then
|
||||
lo
|
||||
else
|
||||
let mid = (lo + hi) / 2 in
|
||||
if cmp (List.hd pile_tops.(mid)) x < 0 then
|
||||
aux (mid+1) hi
|
||||
else
|
||||
aux lo (mid-1)
|
||||
in
|
||||
aux 0 (len-1)
|
||||
in
|
||||
let f len x =
|
||||
let i = bsearch_piles x len in
|
||||
pile_tops.(i) <- x :: if i = 0 then [] else pile_tops.(i-1);
|
||||
if i = len then len+1 else len
|
||||
in
|
||||
let len = List.fold_left f 0 list in
|
||||
List.rev pile_tops.(len-1)
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Node : NSObject {
|
||||
@public
|
||||
id val;
|
||||
Node *back;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation Node
|
||||
@end
|
||||
|
||||
@interface NSArray (LIS)
|
||||
- (NSArray *)longestIncreasingSubsequenceWithComparator:(NSComparator)comparator;
|
||||
@end
|
||||
|
||||
@implementation NSArray (LIS)
|
||||
- (NSArray *)longestIncreasingSubsequenceWithComparator:(NSComparator)comparator {
|
||||
NSMutableArray *pileTops = [[NSMutableArray alloc] init];
|
||||
// sort into piles
|
||||
for (id x in self) {
|
||||
Node *node = [[Node alloc] init];
|
||||
node->val = x;
|
||||
int i = [pileTops indexOfObject:node
|
||||
inSortedRange:NSMakeRange(0, [pileTops count])
|
||||
options:NSBinarySearchingInsertionIndex|NSBinarySearchingFirstEqual
|
||||
usingComparator:^NSComparisonResult(Node *node1, Node *node2) {
|
||||
return comparator(node1->val, node2->val);
|
||||
}];
|
||||
if (i != 0)
|
||||
node->back = pileTops[i-1];
|
||||
pileTops[i] = node;
|
||||
}
|
||||
|
||||
// follow pointers from last node
|
||||
NSMutableArray *result = [[NSMutableArray alloc] init];
|
||||
for (Node *node = [pileTops lastObject]; node; node = node->back)
|
||||
[result addObject:node->val];
|
||||
return [[result reverseObjectEnumerator] allObjects];
|
||||
}
|
||||
@end
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
@autoreleasepool {
|
||||
for (NSArray *d in @[@[@3, @2, @6, @4, @5, @1],
|
||||
@[@0, @8, @4, @12, @2, @10, @6, @14, @1, @9, @5, @13, @3, @11, @7, @15]])
|
||||
NSLog(@"an L.I.S. of %@ is %@", d,
|
||||
[d longestIncreasingSubsequenceWithComparator:^NSComparisonResult(id obj1, id obj2) {
|
||||
return [obj1 compare:obj2];
|
||||
}]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
class Node {
|
||||
public $val;
|
||||
public $back = NULL;
|
||||
}
|
||||
|
||||
function lis($n) {
|
||||
$pileTops = array();
|
||||
// sort into piles
|
||||
foreach ($n as $x) {
|
||||
// binary search
|
||||
$low = 0; $high = count($pileTops)-1;
|
||||
while ($low <= $high) {
|
||||
$mid = (int)(($low + $high) / 2);
|
||||
if ($pileTops[$mid]->val >= $x)
|
||||
$high = $mid - 1;
|
||||
else
|
||||
$low = $mid + 1;
|
||||
}
|
||||
$i = $low;
|
||||
$node = new Node();
|
||||
$node->val = $x;
|
||||
if ($i != 0)
|
||||
$node->back = $pileTops[$i-1];
|
||||
$pileTops[$i] = $node;
|
||||
}
|
||||
$result = array();
|
||||
for ($node = count($pileTops) ? $pileTops[count($pileTops)-1] : NULL;
|
||||
$node != NULL; $node = $node->back)
|
||||
$result[] = $node->val;
|
||||
|
||||
return array_reverse($result);
|
||||
}
|
||||
|
||||
print_r(lis(array(3, 2, 6, 4, 5, 1)));
|
||||
print_r(lis(array(0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15)));
|
||||
?>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
program LisDemo;
|
||||
{$mode objfpc}{$h+}
|
||||
uses
|
||||
SysUtils;
|
||||
|
||||
function Lis(const A: array of Integer): specialize TArray<Integer>;
|
||||
var
|
||||
TailIndex: array of Integer;
|
||||
function CeilIndex(Value, R: Integer): Integer;
|
||||
var
|
||||
L, M: Integer;
|
||||
begin
|
||||
L := 0;
|
||||
while L < R do begin
|
||||
{$PUSH}{$Q-}{$R-}M := (L + R) shr 1;{$POP}
|
||||
if A[TailIndex[M]] < Value then L := M + 1
|
||||
else R := M;
|
||||
end;
|
||||
Result := R;
|
||||
end;
|
||||
var
|
||||
I, J, Len: Integer;
|
||||
Parents: array of Integer;
|
||||
begin
|
||||
Result := nil;
|
||||
if Length(A) = 0 then exit;
|
||||
SetLength(TailIndex, Length(A));
|
||||
SetLength(Parents, Length(A));
|
||||
Len := 1;
|
||||
for I := 1 to High(A) do
|
||||
if A[I] < A[TailIndex[0]] then
|
||||
TailIndex[0] := I
|
||||
else
|
||||
if A[TailIndex[Len-1]] < A[I] then begin
|
||||
Parents[I] := TailIndex[Len - 1];
|
||||
TailIndex[Len] := I;
|
||||
Inc(Len);
|
||||
end else begin
|
||||
J := CeilIndex(A[I], Len - 1);
|
||||
Parents[I] := TailIndex[J - 1];
|
||||
TailIndex[J] := I;
|
||||
end;
|
||||
if Len < 2 then exit([A[0]]);
|
||||
SetLength(Result, Len);
|
||||
J := TailIndex[Len - 1];
|
||||
for I := Len - 1 downto 0 do begin
|
||||
Result[I] := A[J];
|
||||
J := Parents[J];
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure PrintArray(const A: array of Integer);
|
||||
var
|
||||
I: SizeInt;
|
||||
begin
|
||||
Write('[');
|
||||
for I := 0 to High(A) - 1 do
|
||||
Write(A[I], ', ');
|
||||
WriteLn(A[High(A)], ']');
|
||||
end;
|
||||
|
||||
begin
|
||||
PrintArray(Lis([3, 2, 6, 4, 5, 1]));
|
||||
PrintArray(Lis([0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]));
|
||||
PrintArray(Lis([1, 1, 1, 1, 1, 0]));
|
||||
end.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
use strict;
|
||||
|
||||
sub lis {
|
||||
my @l = map [], 1 .. @_;
|
||||
push @{$l[0]}, +$_[0];
|
||||
for my $i (1 .. @_-1) {
|
||||
for my $j (0 .. $i - 1) {
|
||||
if ($_[$j] < $_[$i] and @{$l[$i]} < @{$l[$j]} + 1) {
|
||||
$l[$i] = [ @{$l[$j]} ];
|
||||
}
|
||||
}
|
||||
push @{$l[$i]}, $_[$i];
|
||||
}
|
||||
my ($max, $l) = (0, []);
|
||||
for (@l) {
|
||||
($max, $l) = (scalar(@$_), $_) if @$_ > $max;
|
||||
}
|
||||
return @$l;
|
||||
}
|
||||
|
||||
print join ' ', lis 3, 2, 6, 4, 5, 1;
|
||||
print join ' ', lis 0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15;
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
sub lis {
|
||||
my @pileTops;
|
||||
# sort into piles
|
||||
foreach my $x (@_) {
|
||||
# binary search
|
||||
my $low = 0, $high = $#pileTops;
|
||||
while ($low <= $high) {
|
||||
my $mid = int(($low + $high) / 2);
|
||||
if ($pileTops[$mid]{val} >= $x) {
|
||||
$high = $mid - 1;
|
||||
} else {
|
||||
$low = $mid + 1;
|
||||
}
|
||||
}
|
||||
my $i = $low;
|
||||
my $node = {val => $x};
|
||||
$node->{back} = $pileTops[$i-1] if $i != 0;
|
||||
$pileTops[$i] = $node;
|
||||
}
|
||||
my @result;
|
||||
for (my $node = $pileTops[-1]; $node; $node = $node->{back}) {
|
||||
push @result, $node->{val};
|
||||
}
|
||||
|
||||
return reverse @result;
|
||||
}
|
||||
|
||||
foreach my $r ([3, 2, 6, 4, 5, 1],
|
||||
[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]) {
|
||||
my @d = @$r;
|
||||
my @lis = lis(@d);
|
||||
print "an L.I.S. of [@d] is [@lis]\n";
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">lis</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">n</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">x</span><span style="color: #0000FF;">))</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">p</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">m</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">0</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">lo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">hi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">len</span>
|
||||
<span style="color: #008080;">while</span> <span style="color: #000000;">lo</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">hi</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">mid</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">ceil</span><span style="color: #0000FF;">((</span><span style="color: #000000;">lo</span><span style="color: #0000FF;">+</span><span style="color: #000000;">hi</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">mid</span><span style="color: #0000FF;">]]<</span><span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">lo</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mid</span> <span style="color: #0000FF;">+</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">else</span>
|
||||
<span style="color: #000000;">hi</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">mid</span> <span style="color: #0000FF;">-</span> <span style="color: #000000;">1</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">while</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">lo</span><span style="color: #0000FF;">></span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lo</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">lo</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">i</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">lo</span><span style="color: #0000FF;">></span><span style="color: #000000;">len</span> <span style="color: #008080;">then</span> <span style="color: #000000;">len</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">lo</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">len</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">len</span><span style="color: #0000FF;">></span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">[</span><span style="color: #000000;">len</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">len</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">res</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">k</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">p</span><span style="color: #0000FF;">[</span><span style="color: #000000;">k</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">tests</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">12</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">14</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">13</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">15</span><span style="color: #0000FF;">}}</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #0000FF;">?</span><span style="color: #000000;">lis</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tests</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<!--
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
table(+,+,max)
|
||||
lis_mode(In, Out,OutLen) =>
|
||||
one_is(In, [], Is),
|
||||
Out = reverse(Is),
|
||||
OutLen = Out.length.
|
||||
|
||||
one_is([], Current, Current2) => Current = Current2.
|
||||
one_is([H|T], Current, Final) =>
|
||||
( Current = [], one_is(T, [H], Final));
|
||||
( Current = [H1|_], H1 @< H, one_is(T, [H|Current], Final));
|
||||
one_is(T, Current, Final).
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
lis_cp(S, Res,Z) =>
|
||||
Len = S.len,
|
||||
X = new_list(Len),
|
||||
X :: 0..1,
|
||||
|
||||
increasing_except_0($[X[I]*S[I] : I in 1..Len]),
|
||||
Z #= sum(X),
|
||||
|
||||
solve($[max(Z)],X),
|
||||
% Extract the found LIS
|
||||
Res = [S[I] : I in 1..Len, X[I] == 1].
|
||||
|
||||
%
|
||||
% Ensures that array A is (strictly) increasing if we disregard any 0's
|
||||
%
|
||||
increasing_except_0(A) =>
|
||||
N = A.len,
|
||||
foreach(I in 1..N, J in I+1..N)
|
||||
(A[I] #!= 0 #/\ A[J] #!= 0) #=> (A[I] #< A[J])
|
||||
end.
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import sat. % for lis_cp
|
||||
% import cp. % Slower than sat on larger instances.
|
||||
|
||||
go =>
|
||||
nolog,
|
||||
Tests = [
|
||||
[3,2,6,4,5,1],
|
||||
[0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15],
|
||||
[1,1,1,1],
|
||||
[4,65,2,-31,0,99,83,782,1]
|
||||
],
|
||||
Funs = [lis_mode, lis_cp],
|
||||
|
||||
foreach(Fun in Funs)
|
||||
println(fun=Fun),
|
||||
foreach(Test in Tests)
|
||||
call(Fun,Test,Lis,Len),
|
||||
printf("%w: LIS=%w (len=%d)\n",Test, Lis,Len)
|
||||
end,
|
||||
nl,
|
||||
end,
|
||||
nl.
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
(de longinc (Lst)
|
||||
(let (D NIL R NIL)
|
||||
(for I Lst
|
||||
(cond
|
||||
((< I (last D))
|
||||
(for (Y . X) D
|
||||
(T (> X I) (set (nth D Y) I)) ) )
|
||||
((< I (car R))
|
||||
(set R I)
|
||||
(when D (set (cdr R) (last D))) )
|
||||
(T (when R (queue 'D (car R)))
|
||||
(push 'R I) ) ) )
|
||||
(flip R) ) )
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
(de glutton (L)
|
||||
(let N (pop 'L)
|
||||
(maxi length
|
||||
(recur (N L)
|
||||
(ifn L
|
||||
(list (list N))
|
||||
(mapcan
|
||||
'((R)
|
||||
(if (> (car R) N)
|
||||
(list (cons N R) R)
|
||||
(list (list N) R) ) )
|
||||
(recurse (car L) (cdr L)) ) ) ) ) ) )
|
||||
|
||||
(test (2 4 5)
|
||||
(glutton (3 2 6 4 5 1)))
|
||||
|
||||
(test (2 6 9 11 15)
|
||||
(glutton (8 4 12 2 10 6 14 1 9 5 13 3 11 7 15)))
|
||||
|
||||
(test (-31 0 83 782)
|
||||
(glutton (4 65 2 -31 0 99 83 782 1)) )
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
function Get-LongestSubsequence ( [int[]]$A )
|
||||
{
|
||||
If ( $A.Count -lt 2 ) { return $A }
|
||||
|
||||
# Start with an "empty" pile
|
||||
# (We will only store the top value in each "pile".)
|
||||
$Pile = @( [int]::MaxValue )
|
||||
$Last = 0
|
||||
|
||||
# Hashtable to hold the back pointers
|
||||
$BP = @{}
|
||||
|
||||
# For each number in the orginal sequence...
|
||||
ForEach ( $N in $A )
|
||||
{
|
||||
# Find the first pile with a value greater than N
|
||||
$i = 0..$Last | Where { $N -lt $Pile[$_] } | Select -First 1
|
||||
|
||||
# Place N on the pile
|
||||
$Pile[$i] = $N
|
||||
|
||||
# Set the back pointer for this value to the value of the previous pile
|
||||
$BP["$N"] = $Pile[$i-1]
|
||||
|
||||
# If this is the previously empty pile, add a new empty pile
|
||||
If ( $i -eq $Last )
|
||||
{
|
||||
$Pile += @( [int]::MaxValue )
|
||||
$Last++
|
||||
}
|
||||
}
|
||||
|
||||
# Ignore the empty pile
|
||||
$Last--
|
||||
|
||||
# Start with the value of the last pile
|
||||
$N = $Pile[$Last]
|
||||
$S = @( $N )
|
||||
|
||||
# Add the remainder of the values by walking through the back pointers
|
||||
ForEach ( $i in $Last..1 )
|
||||
{
|
||||
$S += ( $N = $BP["$N"] )
|
||||
}
|
||||
|
||||
# Return the series (reversed into the correct order)
|
||||
return $S[$Last..0]
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
( Get-LongestSubsequence 3, 2, 6, 4, 5, 1 ) -join ', '
|
||||
( Get-LongestSubsequence 0, 8, 4, 12, 2, 10, 6, 16, 14, 1, 9, 5, 13, 3, 11, 7, 15 ) -join ', '
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
lis(In, Out) :-
|
||||
% we ask Prolog to find the longest sequence
|
||||
aggregate(max(N,Is), (one_is(In, [], Is), length(Is, N)), max(_, Res)),
|
||||
reverse(Res, Out).
|
||||
|
||||
|
||||
% we describe the way to find increasing subsequence
|
||||
one_is([], Current, Current).
|
||||
|
||||
|
||||
one_is([H | T], Current, Final) :-
|
||||
( Current = [], one_is(T, [H], Final));
|
||||
( Current = [H1 | _], H1 < H, one_is(T, [H | Current], Final));
|
||||
one_is(T, Current, Final).
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
def longest_increasing_subsequence(X):
|
||||
"""Returns the Longest Increasing Subsequence in the Given List/Array"""
|
||||
N = len(X)
|
||||
P = [0] * N
|
||||
M = [0] * (N+1)
|
||||
L = 0
|
||||
for i in range(N):
|
||||
lo = 1
|
||||
hi = L
|
||||
while lo <= hi:
|
||||
mid = (lo+hi)//2
|
||||
if (X[M[mid]] < X[i]):
|
||||
lo = mid+1
|
||||
else:
|
||||
hi = mid-1
|
||||
|
||||
newL = lo
|
||||
P[i] = M[newL-1]
|
||||
M[newL] = i
|
||||
|
||||
if (newL > L):
|
||||
L = newL
|
||||
|
||||
S = []
|
||||
k = M[L]
|
||||
for i in range(L-1, -1, -1):
|
||||
S.append(X[k])
|
||||
k = P[k]
|
||||
return S[::-1]
|
||||
|
||||
if __name__ == '__main__':
|
||||
for d in [[3,2,6,4,5,1], [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]]:
|
||||
print('a L.I.S. of %s is %s' % (d, longest_increasing_subsequence(d)))
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
def longest_increasing_subsequence(d):
|
||||
'Return one of the L.I.S. of list d'
|
||||
l = []
|
||||
for i in range(len(d)):
|
||||
l.append(max([l[j] for j in range(i) if l[j][-1] < d[i]] or [[]], key=len)
|
||||
+ [d[i]])
|
||||
return max(l, key=len)
|
||||
|
||||
if __name__ == '__main__':
|
||||
for d in [[3,2,6,4,5,1], [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]]:
|
||||
print('a L.I.S. of %s is %s' % (d, longest_increasing_subsequence(d)))
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
from collections import namedtuple
|
||||
from functools import total_ordering
|
||||
from bisect import bisect_left
|
||||
|
||||
@total_ordering
|
||||
class Node(namedtuple('Node_', 'val back')):
|
||||
def __iter__(self):
|
||||
while self is not None:
|
||||
yield self.val
|
||||
self = self.back
|
||||
def __lt__(self, other):
|
||||
return self.val < other.val
|
||||
def __eq__(self, other):
|
||||
return self.val == other.val
|
||||
|
||||
def lis(d):
|
||||
"""Return one of the L.I.S. of list d using patience sorting."""
|
||||
if not d:
|
||||
return []
|
||||
pileTops = []
|
||||
for di in d:
|
||||
j = bisect_left(pileTops, Node(di, None))
|
||||
pileTops[j:j+1] = [Node(di, pileTops[j-1] if j > 0 else None)]
|
||||
return list(pileTops[-1])[::-1]
|
||||
|
||||
if __name__ == '__main__':
|
||||
for d in [[3,2,6,4,5,1],
|
||||
[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]]:
|
||||
print('a L.I.S. of %s is %s' % (d, lis(d)))
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*REXX program finds & displays the longest increasing subsequence from a list of #'s.*/
|
||||
$.=; $.1= 3 2 6 4 5 1 /*define the 1st list to be examined. */
|
||||
$.2= 0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15 /* " " 2nd " " " " */
|
||||
|
||||
do j=1 while $.j\==''; say /* [↓] process all of the list for LIS*/
|
||||
say ' input: ' $.j /*display the (original) input list. */
|
||||
call LIS $.j /*invoke the LIS function. */
|
||||
say 'output: ' result /*display the output (result from LIS)*/
|
||||
end /*j*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
LIS: procedure; parse arg x; n= words(x); if n==0 then return ''
|
||||
p.=; m.= p.
|
||||
do #=1 to n; _= # - 1; @._= word(x, #) /*build an array (@) from input.*/
|
||||
end /*#*/
|
||||
L= 0
|
||||
do j=0 to n-1; lo= 1
|
||||
HI= L
|
||||
do while LO<=HI; middle= (LO+HI) % 2
|
||||
_= m.middle /*create a temporary value for @ index.*/
|
||||
if @._<@.j then LO= middle + 1
|
||||
else HI= middle - 1
|
||||
end /*while*/
|
||||
newLO= LO
|
||||
_= newLO - 1 /*create a temporary value for M index.*/
|
||||
p.j= m._
|
||||
m.newLO= j
|
||||
if newLO>L then L= newLO
|
||||
end /*i*/
|
||||
k= m.L; $= /* [↓] build a list for the result. */
|
||||
do L; $= @.k $; k= p.k /*perform this DO loop L times. */
|
||||
end /*i*/
|
||||
return strip($) /*the result has an extra leading blank*/
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#lang racket/base
|
||||
(require data/gvector)
|
||||
|
||||
(define (gvector-last gv)
|
||||
(gvector-ref gv (sub1 (gvector-count gv))))
|
||||
|
||||
(define (lis-patience-sort input-list)
|
||||
(let ([piles (gvector)])
|
||||
(for ([item (in-list input-list)])
|
||||
(insert-item! piles item))
|
||||
(reverse (gvector-last piles))))
|
||||
|
||||
(define (insert-item! piles item)
|
||||
(if (zero? (gvector-count piles))
|
||||
(gvector-add! piles (cons item '()))
|
||||
(cond
|
||||
[(not (<= item (car (gvector-last piles))))
|
||||
(gvector-add! piles (cons item (gvector-last piles)))]
|
||||
[(<= item (car (gvector-ref piles 0)))
|
||||
(gvector-set! piles 0 (cons item '()))]
|
||||
[else (let loop ([first 1] [last (sub1 (gvector-count piles))])
|
||||
(if (= first last)
|
||||
(gvector-set! piles first (cons item (gvector-ref piles (sub1 first))))
|
||||
(let ([middle (quotient (+ first last) 2)])
|
||||
(if (<= item (car (gvector-ref piles middle)))
|
||||
(loop first middle)
|
||||
(loop (add1 middle) last)))))])))
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
sub lis(@d) {
|
||||
my @l = [].item xx @d;
|
||||
@l[0].push: @d[0];
|
||||
for 1 ..^ @d -> $i {
|
||||
for ^$i -> $j {
|
||||
if @d[$j] < @d[$i] && @l[$i] < @l[$j] + 1 {
|
||||
@l[$i] = [ @l[$j][] ]
|
||||
}
|
||||
}
|
||||
@l[$i].push: @d[$i];
|
||||
}
|
||||
return max :by(*.elems), @l;
|
||||
}
|
||||
|
||||
say lis([3,2,6,4,5,1]);
|
||||
say lis([0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15]);
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
sub lis(@deck is copy) {
|
||||
my @S = [@deck.shift() => Nil].item;
|
||||
for @deck -> $card {
|
||||
with first { @S[$_][*-1].key > $card }, ^@S -> $i {
|
||||
@S[$i].push: $card => @S[$i-1][*-1] // Nil
|
||||
} else {
|
||||
@S.push: [ $card => @S[*-1][*-1] // Nil ].item
|
||||
}
|
||||
}
|
||||
reverse map *.key, (
|
||||
@S[*-1][*-1], *.value ...^ !*.defined
|
||||
)
|
||||
}
|
||||
|
||||
say lis <3 2 6 4 5 1>;
|
||||
say lis <0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15>;
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
# Project : Longest increasing subsequence
|
||||
|
||||
tests = [[3, 2, 6, 4, 5, 1], [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]]
|
||||
res = []
|
||||
for x=1 to len(tests)
|
||||
lis(tests[x])
|
||||
showarray(res)
|
||||
end
|
||||
|
||||
func lis(X)
|
||||
N = len(X)
|
||||
P = list(N)
|
||||
M = list(N)
|
||||
for nr = 1 to len(P)
|
||||
P[nr] = 0
|
||||
next
|
||||
for nr = 1 to len(M)
|
||||
P[nr] = 0
|
||||
next
|
||||
len = 0
|
||||
for i=1 to N
|
||||
lo = 1
|
||||
hi = len
|
||||
while lo <= hi
|
||||
mid = floor((lo+hi)/2)
|
||||
if X[M[mid]]<X[i]
|
||||
lo = mid + 1
|
||||
else
|
||||
hi = mid - 1
|
||||
ok
|
||||
end
|
||||
if lo>1
|
||||
P[i] = M[lo-1]
|
||||
ok
|
||||
M[lo] = i
|
||||
if lo>len
|
||||
len = lo
|
||||
ok
|
||||
next
|
||||
res = list(len)
|
||||
if len>0
|
||||
k = M[len]
|
||||
for i=len to 1 step -1
|
||||
res[i] = X[k]
|
||||
k = P[k]
|
||||
next
|
||||
ok
|
||||
return res
|
||||
|
||||
func showarray(vect)
|
||||
see "{"
|
||||
svect = ""
|
||||
for n = 1 to len(vect)
|
||||
svect = svect + vect[n] + ", "
|
||||
next
|
||||
svect = left(svect, len(svect) - 2)
|
||||
see svect
|
||||
see "}" + nl
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
Node = Struct.new(:val, :back)
|
||||
|
||||
def lis(n)
|
||||
pileTops = []
|
||||
# sort into piles
|
||||
for x in n
|
||||
# binary search
|
||||
low, high = 0, pileTops.size-1
|
||||
while low <= high
|
||||
mid = low + (high - low) / 2
|
||||
if pileTops[mid].val >= x
|
||||
high = mid - 1
|
||||
else
|
||||
low = mid + 1
|
||||
end
|
||||
end
|
||||
i = low
|
||||
node = Node.new(x)
|
||||
node.back = pileTops[i-1] if i > 0
|
||||
pileTops[i] = node
|
||||
end
|
||||
|
||||
result = []
|
||||
node = pileTops.last
|
||||
while node
|
||||
result.unshift(node.val)
|
||||
node = node.back
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
p lis([3, 2, 6, 4, 5, 1])
|
||||
p lis([0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15])
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
fn lis(x: &[i32])-> Vec<i32> {
|
||||
let n = x.len();
|
||||
let mut m = vec![0; n];
|
||||
let mut p = vec![0; n];
|
||||
let mut l = 0;
|
||||
|
||||
for i in 0..n {
|
||||
let mut lo = 1;
|
||||
let mut hi = l;
|
||||
|
||||
while lo <= hi {
|
||||
let mid = (lo + hi) / 2;
|
||||
|
||||
if x[m[mid]] <= x[i] {
|
||||
lo = mid + 1;
|
||||
} else {
|
||||
hi = mid - 1;
|
||||
}
|
||||
}
|
||||
|
||||
let new_l = lo;
|
||||
p[i] = m[new_l - 1];
|
||||
m[new_l] = i;
|
||||
|
||||
if new_l > l {
|
||||
l = new_l;
|
||||
}
|
||||
}
|
||||
|
||||
let mut o = vec![0; l];
|
||||
let mut k = m[l];
|
||||
for i in (0..l).rev() {
|
||||
o[i] = x[k];
|
||||
k = p[k];
|
||||
}
|
||||
|
||||
o
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let list = vec![3, 2, 6, 4, 5, 1];
|
||||
println!("{:?}", lis(&list));
|
||||
let list = vec![0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15];
|
||||
println!("{:?}", lis(&list));
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
object LongestIncreasingSubsequence extends App {
|
||||
val tests = Map(
|
||||
"3,2,6,4,5,1" -> Seq("2,4,5", "3,4,5"),
|
||||
"0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15" -> Seq("0,2,6,9,11,15", "0,2,6,9,13,15", "0,4,6,9,13,15", "0,4,6,9,11,15")
|
||||
)
|
||||
|
||||
def lis(l: Array[Int]): Seq[Array[Int]] =
|
||||
if (l.length < 2) Seq(l)
|
||||
else {
|
||||
def increasing(done: Array[Int], remaining: Array[Int]): Seq[Array[Int]] =
|
||||
if (remaining.isEmpty) Seq(done)
|
||||
else
|
||||
(if (remaining.head > done.last)
|
||||
increasing(done :+ remaining.head, remaining.tail)
|
||||
else Nil) ++ increasing(done, remaining.tail) // all increasing combinations
|
||||
|
||||
val all = (1 to l.length)
|
||||
.flatMap(i => increasing(l take i takeRight 1, l.drop(i + 1)))
|
||||
.sortBy(-_.length)
|
||||
all.takeWhile(_.length == all.head.length) // longest of all increasing combinations
|
||||
}
|
||||
|
||||
def asInts(s: String): Array[Int] = s split "," map (_.toInt)
|
||||
|
||||
assert(tests forall {
|
||||
case (given, expect) =>
|
||||
val allLongests: Seq[Array[Int]] = lis(asInts(given))
|
||||
println(
|
||||
s"$given has ${allLongests.length} longest increasing subsequences, e.g. ${
|
||||
allLongests.last.mkString(",")}")
|
||||
allLongests.forall(lis => expect.contains(lis.mkString(",")))
|
||||
})
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
def powerset[A](s: List[A]) = (0 to s.size).map(s.combinations(_)).reduce(_++_)
|
||||
def isSorted(l:List[Int])(f: (Int, Int) => Boolean) = l.view.zip(l.tail).forall(x => f(x._1,x._2))
|
||||
def sequence(set: List[Int])(f: (Int, Int) => Boolean) = powerset(set).filter(_.nonEmpty).filter(x => isSorted(x)(f)).toList.maxBy(_.length)
|
||||
|
||||
sequence(set)(_<_)
|
||||
sequence(set)(_>_)
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
(define (lis less? lst)
|
||||
(define pile-tops (make-vector (length lst)))
|
||||
(define (bsearch-piles x len)
|
||||
(let aux ((lo 0)
|
||||
(hi (- len 1)))
|
||||
(if (> lo hi)
|
||||
lo
|
||||
(let ((mid (quotient (+ lo hi) 2)))
|
||||
(if (less? (car (vector-ref pile-tops mid)) x)
|
||||
(aux (+ mid 1) hi)
|
||||
(aux lo (- mid 1)))))))
|
||||
(let aux ((len 0)
|
||||
(lst lst))
|
||||
(if (null? lst)
|
||||
(reverse (vector-ref pile-tops (- len 1)))
|
||||
(let* ((x (car lst))
|
||||
(i (bsearch-piles x len)))
|
||||
(vector-set! pile-tops i (cons x (if (= i 0)
|
||||
'()
|
||||
(vector-ref pile-tops (- i 1)))))
|
||||
(aux (if (= i len) (+ len 1) len) (cdr lst))))))
|
||||
|
||||
(display (lis < '(3 2 6 4 5 1))) (newline)
|
||||
(display (lis < '(0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15))) (newline)
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
func lis(a) {
|
||||
var l = a.len.of { [] }
|
||||
l[0] << a[0]
|
||||
for i in (1..a.end) {
|
||||
for j in ^i {
|
||||
if ((a[j] < a[i]) && (l[i].len < l[j].len+1)) {
|
||||
l[i] = [l[j]...]
|
||||
}
|
||||
}
|
||||
l[i] << a[i]
|
||||
}
|
||||
l.max_by { .len }
|
||||
}
|
||||
|
||||
say lis(%i<3 2 6 4 5 1>)
|
||||
say lis(%i<0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15>)
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
func lis(deck) {
|
||||
var pileTops = []
|
||||
deck.each { |x|
|
||||
var low = 0;
|
||||
var high = pileTops.end
|
||||
while (low <= high) {
|
||||
var mid = ((low + high) // 2)
|
||||
if (pileTops[mid]{:val} >= x) {
|
||||
high = mid-1
|
||||
} else {
|
||||
low = mid+1
|
||||
}
|
||||
}
|
||||
var i = low
|
||||
var node = Hash(val => x)
|
||||
node{:back} = pileTops[i-1] if (i != 0)
|
||||
pileTops[i] = node
|
||||
}
|
||||
var result = []
|
||||
for (var node = pileTops[-1]; node; node = node{:back}) {
|
||||
result << node{:val}
|
||||
}
|
||||
result.reverse
|
||||
}
|
||||
|
||||
say lis(%i<3 2 6 4 5 1>)
|
||||
say lis(%i<0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15>)
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
fun lis cmp n =
|
||||
let
|
||||
val pile_tops = DynamicArray.array (length n, [])
|
||||
fun bsearch_piles x =
|
||||
let
|
||||
fun aux (lo, hi) =
|
||||
if lo > hi then
|
||||
lo
|
||||
else
|
||||
let
|
||||
val mid = (lo + hi) div 2
|
||||
in
|
||||
if cmp (hd (DynamicArray.sub (pile_tops, mid)), x) = LESS then
|
||||
aux (mid+1, hi)
|
||||
else
|
||||
aux (lo, mid-1)
|
||||
end
|
||||
in
|
||||
aux (0, DynamicArray.bound pile_tops)
|
||||
end
|
||||
fun f x =
|
||||
let
|
||||
val i = bsearch_piles x
|
||||
in
|
||||
DynamicArray.update (pile_tops, i,
|
||||
x :: (if i = 0 then [] else DynamicArray.sub (pile_tops, i-1)))
|
||||
end
|
||||
in
|
||||
app f n;
|
||||
rev (DynamicArray.sub (pile_tops, DynamicArray.bound pile_tops))
|
||||
end
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import Foundation
|
||||
|
||||
extension Array where Element: Comparable {
|
||||
@inlinable
|
||||
public func longestIncreasingSubsequence() -> [Element] {
|
||||
var startI = [Int](repeating: 0, count: count)
|
||||
var endI = [Int](repeating: 0, count: count + 1)
|
||||
var len = 0
|
||||
|
||||
for i in 0..<count {
|
||||
var lo = 1
|
||||
var hi = len
|
||||
|
||||
while lo <= hi {
|
||||
let mid = Int(ceil((Double(lo + hi)) / 2))
|
||||
|
||||
if self[endI[mid]] <= self[i] {
|
||||
lo = mid + 1
|
||||
} else {
|
||||
hi = mid - 1
|
||||
}
|
||||
}
|
||||
|
||||
startI[i] = endI[lo-1]
|
||||
endI[lo] = i
|
||||
|
||||
if lo > len {
|
||||
len = lo
|
||||
}
|
||||
}
|
||||
|
||||
var s = [Element]()
|
||||
var k = endI[len]
|
||||
|
||||
for _ in 0..<len {
|
||||
s.append(self[k])
|
||||
k = startI[k]
|
||||
}
|
||||
|
||||
return s.reversed()
|
||||
}
|
||||
}
|
||||
|
||||
let l1 = [3, 2, 6, 4, 5, 1]
|
||||
let l2 = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]
|
||||
|
||||
print("\(l1) = \(l1.longestIncreasingSubsequence())")
|
||||
print("\(l2) = \(l2.longestIncreasingSubsequence())")
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package require Tcl 8.6
|
||||
|
||||
proc longestIncreasingSubsequence {sequence} {
|
||||
# Get the increasing subsequences (and their lengths)
|
||||
set subseq [list 1 [lindex $sequence 0]]
|
||||
foreach value $sequence {
|
||||
set max {}
|
||||
foreach {len item} $subseq {
|
||||
if {[lindex $item end] < $value} {
|
||||
if {[llength [lappend item $value]] > [llength $max]} {
|
||||
set max $item
|
||||
}
|
||||
} elseif {![llength $max]} {
|
||||
set max [list $value]
|
||||
}
|
||||
}
|
||||
lappend subseq [llength $max] $max
|
||||
}
|
||||
# Pick the longest subsequence; -stride requires Tcl 8.6
|
||||
return [lindex [lsort -stride 2 -index 0 $subseq] end]
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
puts [longestIncreasingSubsequence {3 2 6 4 5 1}]
|
||||
puts [longestIncreasingSubsequence {0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15}]
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
Function LIS(arr)
|
||||
n = UBound(arr)
|
||||
Dim p()
|
||||
ReDim p(n)
|
||||
Dim m()
|
||||
ReDim m(n)
|
||||
l = 0
|
||||
For i = 0 To n
|
||||
lo = 1
|
||||
hi = l
|
||||
Do While lo <= hi
|
||||
middle = Int((lo+hi)/2)
|
||||
If arr(m(middle)) < arr(i) Then
|
||||
lo = middle + 1
|
||||
Else
|
||||
hi = middle - 1
|
||||
End If
|
||||
Loop
|
||||
newl = lo
|
||||
p(i) = m(newl-1)
|
||||
m(newl) = i
|
||||
If newL > l Then
|
||||
l = newl
|
||||
End If
|
||||
Next
|
||||
Dim s()
|
||||
ReDim s(l)
|
||||
k = m(l)
|
||||
For i = l-1 To 0 Step - 1
|
||||
s(i) = arr(k)
|
||||
k = p(k)
|
||||
Next
|
||||
LIS = Join(s,",")
|
||||
End Function
|
||||
|
||||
WScript.StdOut.WriteLine LIS(Array(3,2,6,4,5,1))
|
||||
WScript.StdOut.WriteLine LIS(Array(0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15))
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
var longestIncreasingSubsequence = Fn.new { |x|
|
||||
var n = x.count
|
||||
if (n == 0) return []
|
||||
if (n == 1) return x
|
||||
var p = List.filled(n, 0)
|
||||
var m = List.filled(n+1, 0)
|
||||
var len = 0
|
||||
for (i in 0...n) {
|
||||
var lo = 1
|
||||
var hi = len
|
||||
while (lo <= hi) {
|
||||
var mid = ((lo + hi)/2).ceil
|
||||
if (x[m[mid]] < x[i]) {
|
||||
lo = mid + 1
|
||||
} else {
|
||||
hi = mid - 1
|
||||
}
|
||||
}
|
||||
var newLen = lo
|
||||
p[i] = m[newLen - 1]
|
||||
m[newLen] = i
|
||||
if (newLen > len) len = newLen
|
||||
}
|
||||
var s = List.filled(len, 0)
|
||||
var k = m[len]
|
||||
for (i in len-1..0) {
|
||||
s[i] = x[k]
|
||||
k = p[k]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
var lists = [
|
||||
[3, 2, 6, 4, 5, 1],
|
||||
[0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]
|
||||
]
|
||||
lists.each { |l| System.print(longestIncreasingSubsequence.call(l)) }
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
fcn longestSequence(ns){ // based on Patience sorting
|
||||
piles:=L();
|
||||
backPtr:='wrap(np){ return(np-1,if(np) piles[np-1].len()-1 else -1) }; // maybe (-1,-1)
|
||||
foreach n in (ns){ newPile:=True; // create list of sorted lists
|
||||
foreach e,p in (piles.enumerate()){
|
||||
if(n<p[-1][0]){
|
||||
p.del(1,-1) // only need the first and last elements
|
||||
.append(T(n,backPtr(e))); newPile=False;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(newPile) piles.append(L(T(n,backPtr(piles.len()))));
|
||||
}
|
||||
reg r=L(),p=-1,n=0;
|
||||
do{ n,p=piles[p][n]; r.write(n); p,n=p; }while(p!=-1);
|
||||
r.reverse()
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
foreach ns in (T(T(1),T(3,2,6,4,5,1),T(4,65,2,-31,0,99,83,782,1),
|
||||
T(0,8,4,12,2,10,6,14,1,9,5,13,3,11,7,15),"foobar")){
|
||||
s:=longestSequence(ns);
|
||||
println(s.len(),": ",s," from ",ns);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue