#!/usr/bin/ruby

#
## https://rosettacode.org/wiki/Longest_increasing_subsequence
#

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
}

var a = lis(%i<3 2 6 4 5 1>)
var b = lis(%i<0 8 4 12 2 10 6 14 1 9 5 13 3 11 7 15>)

say a
say b

assert_eq(a, [2, 4, 5])
assert_eq(b, [0, 2, 6, 9, 11, 15])