extra-iterable
Version:
An [iterable] is a sequence of values.<br>
1,903 lines • 172 kB
JavaScript
import { IDENTITY, COMPARE } from "@nodef/extra-function";
import { mod } from "@nodef/extra-math";
// CONSTANTS
// =========
/** End of iterable. */ export const END = Number.MAX_SAFE_INTEGER;
/** Empty iterable. */ const EMPTY = [].values();
// METHODS
// =======
// HELPERS
// -------
/** Convert an iterable to set. */ function toSet(x, fm = null) {
if (!fm) return new Set(x);
const a = new Set();
let i = -1;
for (const v of x)a.add(fm(v, ++i, x));
return a;
}
// ABOUT
// -----
/**
* Check if value is an iterable.
* @param v a value
* @returns v is iterable?
*/ export function is(v) {
return v != null && typeof v[Symbol.iterator] === "function";
}
/**
* Check if value is an iterator.
* @param v a value
* @returns v implements \{next(), return?(), throw?()\}?
*/ export function isIterator(v) {
return v != null && typeof v.next === "function";
}
/**
* Check if value is a list (iterable & !string).
* @param v a value
* @returns v is list?
*/ export function isList(v) {
return is(v) && typeof v !== "string";
}
/**
* Get iterator of an iterable.
* @param x an iterable
* @returns x\[\<iterator\>\]()
*/ export function iterator(x) {
return x[Symbol.iterator]();
}
/**
* List all indices.
* @param x an iterable
* @returns 0, 1, ..., |x|-1
*/ export function* keys(x) {
let i = -1;
for (const _ of x)yield ++i;
}
/**
* List all values.
* @param x an iterable
* @returns v₀, v₁, ... | vᵢ = x[i]
*/ export function* values(x) {
yield* x;
}
export { values as toOnce };
/**
* List all index-value pairs.
* @param x an iterable
* @returns [0, v₀], [1, v₁], ... | vᵢ = x[i]
*/ export function* entries(x) {
let i = -1;
for (const v of x)yield [
++i,
v
];
}
// GENERATE
// --------
/**
* Convert an iterable-like to iterable.
* @param x an iterator/iterable
* @returns x as iterable
*/ export function from(x) {
if (is(x)) return x;
return fromIterator(x);
}
/**
* Convert an iterator to iterable.
* @param x an iterator/iterable
* @returns x as iterable
*/ export function fromIterator(x) {
return {
[Symbol.iterator]: ()=>x
};
}
/**
* Generate iterable from given number range.
* @param v start number [0]
* @param V stop number, excluding [END]
* @param dv step size [1]
* @returns v, v+dv, v+2dv, ...
*/ export function* fromRange(v = 0, V = END, dv = 1) {
const N = (V - v) / dv;
for(let n = 0; n < N; ++n, v += dv)yield v;
}
/**
* Generate iterable from repeated function invocation.
* @param fn function (impure)
* @param args arguments
* @returns fn(...args), fn(...args), ...
*/ export function* fromInvocation(fn, ...args) {
for(;;)yield fn(...args);
}
export { fromInvocation as fromCall };
/**
* Generate iterable from repeated function application.
* @param fm map function (v, i)
* @param v start value
* @returns v, fm(v), fm(fm(v)), ...
*/ export function* fromApplication(fm, v) {
yield v;
for(let i = 1;; ++i)yield v = fm(v, i, null);
}
export { fromApplication as fromApply };
// BEHAVIOR
// --------
/**
* Check if an iterable can iterated only once.
* @param x an iterable
* @returns x\[\<iterator\>\] = x?
*/ export function isOnce(x) {
return x[Symbol.iterator]() === x;
}
/**
* Check if an iterable can be iterated many times.
* @param x an iterable
* @returns x\[\<iterator\>\] ≠ x?
*/ export function isMany(x) {
return !isOnce(x);
}
/**
* Convert a once-like iterable to many.
* @param x an iterable
* @param now consume immediately? [false]
* @returns x' | x' = x; x' can be iterated multiple times
*/ export function toMany(x, now = false) {
if (!isOnce(x)) return x;
return now ? Array.from(x) : toManyLate(x[Symbol.iterator](), []);
}
export { toMany as many };
function toManyLate(ix, a) {
return {
[Symbol.iterator]: ()=>{
let i = -1;
return {
next: ()=>{
if (++i < a.length) return {
value: a[i],
done: false
};
const { value, done } = ix.next();
if (!done) a[i] = value;
return {
value,
done
};
}
};
}
};
}
/**
* Generate a function that iterates over values upon invocation.
* @param x an iterable
* @returns fn | fn() → x[0], fn() → x[1], ...
*/ export function toInvokable(x) {
const ix = x[Symbol.iterator]();
return ()=>ix.next().value;
}
export { toInvokable as toCallable };
export { toInvokable as callable };
// LENGTH
// ------
/**
* Check if an iterable is empty.
* @param x an iterable
* @returns |x| = 0?
*/ export function isEmpty(x) {
for (const _ of x)return false;
return true;
}
/**
* Find the length of an iterable.
* @param x an iterable
* @param i start index [0]
* @param I end index [END]
* @returns |x[i..I]|
*/ export function length(x, i = 0, I = END) {
let j = -1, n = 0;
for (const _ of x)if (++j >= i && j < I) ++n;
return n;
}
export { length as size };
/**
* Get zero-based index for element in iterable.
* @param x an iterable
* @param i index (-ve: from right)
* @returns i' | x[i'] = x[i]; i' ∈ [0, |x|]
*/ export function index(x, i) {
const X = length(x);
return i >= 0 ? Math.min(i, X) : Math.max(X + i, 0);
}
/**
* Get index range for part of iterable.
* @param x an iterable
* @param i start index (-ve: from right) [0]
* @param I end index (-ve: from right) [END]
* @returns [i', I'] | i' ≤ I'; i', I' ∈ [0, |x|]
*/ export function indexRange(x, i = 0, I = END) {
const X = length(x);
i = i >= 0 ? Math.min(i, X) : Math.max(X + i, 0);
I = I >= 0 ? Math.min(I, X) : Math.max(X + I, 0);
return [
i,
Math.max(i, I)
];
}
// COMPARE
// -------
/**
* Compare two iterables.
* @param x an iterable
* @param y another iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x<y: -1, x=y: 0, x>y: 1
*/ export function compare(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const ix = x[Symbol.iterator]();
const iy = y[Symbol.iterator]();
let u, v;
for(let i = 0;; ++i){
u = ix.next();
v = iy.next();
if (u.done || v.done) break;
const u1 = fm(u.value, i, x);
const v1 = fm(v.value, i, y);
const c = fc(u1, v1);
if (c !== 0) return c;
}
return (v.done ? 1 : 0) - (u.done ? 1 : 0);
}
/**
* Check if two iterables are equal.
* @param x an iterable
* @param y another iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x=y?
*/ export function isEqual(x, y, fc = null, fm = null) {
return compare(x, y, fc, fm) === 0;
}
// GET/SET
// -------
/**
* Get value at index.
* @param x an iterable
* @param i index
* @returns x[i]
*/ export function get(x, i) {
let j = -1;
for (const v of x)if (++j === i) return v;
}
/**
* Get values at indices.
* @param x an iterable
* @param is indices (sorted)
* @returns x[i₀], x[i₁], ... | [i₀, i₁, ...] = is
*/ export function* getAll(x, is) {
let i = 0, j = -1;
const IS = is.length;
for (const v of x){
if (is[i] !== ++j) continue;
do {
yield v;
}while (++i < IS && is[i] === is[i - 1])
if (i >= IS) break;
}
for(; i < IS; ++i)yield;
}
/**
* Get value at path in a nested iterable.
* @param x a nested iterable
* @param p path
* @returns x[i₀][i₁][...] | [i₀, i₁, ...] = p
*/ export function getPath(x, p) {
let xany = x;
for (const i of p)xany = is(xany) ? get(xany, i) : undefined;
return xany;
}
/**
* Check if nested iterable has a path.
* @param x a nested iterable
* @param p path
* @returns x[i₀][i₁][...] exists? | [i₀, i₁, ...] = p
*/ export function hasPath(x, p) {
return getPath(x, p) !== undefined;
}
/**
* Set value at index.
* @param x an iterable
* @param i index
* @param v value
* @returns x' | x' = x; x'[i] = v
*/ export function* set(x, i, v) {
let j = -1;
for (const u of x)yield ++j === i ? v : u;
if (j >= i) return;
for(; ++j < i;)yield;
yield v;
}
/**
* Exchange two values.
* @param x an iterable
* @param i an index
* @param j another index
* @returns x' | x' = x; x'[i] = x[j]; x'[j] = x[i]
*/ export function* swap(x, i, j) {
if (i === j) {
yield* x;
return;
}
const k = Math.min(i, j);
const l = Math.max(i, j);
let mid = [];
let vk = undefined;
i = -1;
for (const v of x){
if (++i < k || i > l) yield v;
else if (i === k) vk = v;
else if (i < l) mid.push(v);
else {
yield v;
yield* mid;
yield vk;
mid = [];
}
}
}
/**
* Remove value at index.
* @param x an iterable
* @param i index
* @returns x[0..i] ⧺ x[i+1..]
*/ export function* remove(x, i) {
yield* splice(x, i, 1);
}
// PROPERTY
// --------
/**
* Count values which satisfy a test.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns Σtᵢ | tᵢ = 1 if ft(vᵢ) else 0; vᵢ ∈ x
*/ export function count(x, ft) {
let i = -1, a = 0;
for (const v of x)if (ft(v, ++i, x)) ++a;
return a;
}
/**
* Count occurrences of values.
* @param x an array
* @param fm map function (v, i, x)
* @returns Map \{value ⇒ count\}
*/ export function countAs(x, fm = null) {
fm = fm || IDENTITY;
let i = -1;
const a = new Map();
for (const v of x){
const v1 = fm(v, ++i, x);
a.set(v1, (a.get(v1) || 0) + 1);
}
return a;
}
/**
* Find smallest value.
* @param x an iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns v | v ≤ vᵢ; vᵢ ∈ x
*/ export function min(x, fc = null, fm = null) {
return rangeEntries(x, fc, fm)[0][1];
}
/**
* Find largest value.
* @param x an iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns v | v ≥ vᵢ; vᵢ ∈ x
*/ export function max(x, fc = null, fm = null) {
return rangeEntries(x, fc, fm)[1][1];
}
/**
* Find smallest and largest values.
* @param x an iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns [min_value, max_value]
*/ export function range(x, fc = null, fm = null) {
const [a, b] = rangeEntries(x, fc, fm);
return [
a[1],
b[1]
];
}
/**
* Find smallest entry.
* @param x an iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns [min_index, min_value]
*/ export function minEntry(x, fc = null, fm = null) {
return rangeEntries(x, fc, fm)[0];
}
/**
* Find largest entry.
* @param x an iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns [max_index, max_value]
*/ export function maxEntry(x, fc = null, fm = null) {
return rangeEntries(x, fc, fm)[1];
}
/**
* Find smallest and largest entries.
* @param x an iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns [min_entry, max_entry]
*/ export function rangeEntries(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
let mi = -1, mu, mv;
let ni = -1, nu, nv;
let i = -1;
for (const u of x){
const v = fm(u, ++i, x);
if (i === 0 || fc(v, mv) < 0) {
mi = i;
mu = u;
mv = v;
}
if (i === 0 || fc(v, nv) > 0) {
ni = i;
nu = u;
nv = v;
}
}
return [
[
mi,
mu
],
[
ni,
nu
]
];
}
// PART
// ----
/**
* Get part of an iterable.
* @param x an iterable
* @param i start index (-ve: from right) [0]
* @param I end index (-ve: from right) [END]
* @returns x[i..I]
*/ export function slice(x, i = 0, I = END) {
if (i >= 0 && I >= 0) return slicePos(x, i, I);
else if (i >= 0 && I < 0) return slicePosNeg(x, i, I);
else return sliceNeg(x, i, I);
}
function* slicePos(x, i, I) {
let k = -1;
for (const v of x){
if (++k >= I) break;
if (k >= i) yield v;
}
}
function* slicePosNeg(x, i, I) {
let j = 0, k = -1;
const a = [], A = -I;
for (const v of x){
if (++k < i) continue;
if (a.length >= A) yield a[j];
a[j] = v;
j = (j + 1) % A;
}
}
function* sliceNeg(x, i, I) {
let j = 0, X = 0;
const a = [], A = -i;
for (const v of x){
a[j] = v;
j = (j + 1) % A;
++X;
}
i = Math.max(X + i, 0);
I = I < 0 ? Math.max(X + I, 0) : Math.min(I, X);
const n = Math.max(I - i, 0);
const J = Math.max(j + n - A, 0);
yield* a.slice(j, j + n);
yield* a.slice(0, J);
}
/**
* Get first value.
* @param x an iterable
* @param vd default value
* @returns x[0] || vd
*/ export function head(x, vd) {
for (const v of x)return v;
return vd;
}
/**
* Get last value.
* @param x an iterable
* @param vd default value
* @returns x[|x|-1]
*/ export function last(x, vd) {
let v = vd;
for (v of x);
return v;
}
/**
* Get values except first.
* @param x an iterable
* @returns x[1..|x|]
*/ export function* tail(x) {
let i = -1;
for (const v of x)if (++i > 0) yield v;
}
export { tail as shift };
/**
* Get values except last.
* @param x an iterable
* @returns x[0..|x|-1]
*/ export function* init(x) {
let u = undefined, i = -1;
for (const v of x){
if (++i > 0) yield u;
u = v;
}
}
export { init as pop };
/**
* Get values from left.
* @param x an iterable
* @param n number of values
* @returns x[0..n]
*/ export function left(x, n) {
return slice(x, 0, n);
}
/**
* Get values from right.
* @param x an iterable
* @param n number of values
* @returns x[-n..]
*/ export function right(x, n) {
return n !== 0 ? slice(x, -n) : EMPTY;
}
/**
* Get values from middle.
* @param x an iterable
* @param i start index
* @param n number of values [1]
* @returns x[i..i+n]
*/ export function middle(x, i, n = 1) {
return slice(x, i, i + n);
}
/**
* Keep first n values only.
* @param x an iterable
* @param n number of values [1]
* @returns x[0..n]
*/ export function take(x, n = 1) {
return slice(x, 0, n);
}
/**
* Keep last n values only.
* @param x an iterable
* @param n number of values [1]
* @returns x[-n..]
*/ export function takeRight(x, n = 1) {
return n > 0 ? slice(x, -n) : EMPTY;
}
/**
* Keep values from left, while a test passes.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns x[0..T-1] | ft(x[i]) = true ∀ i ∈ [0, T-1] & ft(x[T]) = false
*/ export function* takeWhile(x, ft) {
let i = -1;
for (const v of x){
if (ft(v, ++i, x)) yield v;
else return;
}
}
/**
* Keep values from right, while a test passes.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns x[T..] | ft(x[i]) = true ∀ i ∈ [T, |x|-1] & ft(x[T-1]) = false
*/ export function* takeWhileRight(x, ft) {
const a = [];
let i = -1;
for (const v of x){
if (ft(v, ++i, x)) a.push(v);
else a.length = 0;
}
yield* a;
}
/**
* Discard first n values only.
* @param x an iterable
* @param n number of values [1]
* @returns x[n..]
*/ export function drop(x, n = 1) {
return slice(x, n);
}
/**
* Discard last n values only.
* @param x an iterable
* @param n number of values [1]
* @returns x[0..-n]
*/ export function dropRight(x, n = 1) {
return n > 0 ? slice(x, 0, -n) : values(x);
}
/**
* Discard values from left, while a test passes.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns x[T..] | ft(x[i]) = true ∀ i ∈ [0, T-1] & ft(x[T]) = false
*/ export function* dropWhile(x, ft) {
let c = true, i = -1;
for (const v of x){
c = c && ft(v, ++i, x);
if (!c) yield v;
}
}
/**
* Discard values from right, while a test passes.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns x[0..T-1] | ft(x[i]) = true ∀ i ∈ [T, |x|-1] & ft(x[T-1]) = false
*/ export function* dropWhileRight(x, ft) {
const a = [];
let i = -1;
for (const v of x){
if (ft(v, ++i, x)) a.push(v);
else {
yield* a;
yield v;
a.length = 0;
}
}
}
// FIND
// ----
/**
* Check if iterable has a value.
* @param x an iterable
* @param v search value
* @param i start index [0]
* @returns v ∈ x[i..]?
*/ export function includes(x, v, i = 0) {
return hasValue(slice(x, i), v);
}
/**
* Find first index of a value.
* @param x an iterable
* @param v search value
* @param i start index [0]
* @returns index of v in x[i..] if found else -1
*/ export function indexOf(x, v, i = 0) {
const a = searchValue(slice(x, i), v);
return a >= 0 ? a + i : a;
}
/**
* Find last index of a value.
* @param x an iterable
* @param v search value
* @param i start index [END-1]
* @returns last index of v in x[0..i] if found else -1
*/ export function lastIndexOf(x, v, i = END - 1) {
return searchValueRight(slice(x, 0, i + 1), v);
}
/**
* Find first value passing a test.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns first v | ft(v) = true; v ∈ x
*/ export function find(x, ft) {
let i = -1;
for (const v of x)if (ft(v, ++i, x)) return v;
}
/**
* Find last value passing a test.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns last v | ft(v) = true; v ∈ x
*/ export function findRight(x, ft) {
let i = -1, a;
for (const v of x)if (ft(v, ++i, x)) a = v;
return a;
}
/**
* Scan from left, while a test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns first index where test fails
*/ export function scanWhile(x, ft) {
let i = -1;
for (const v of x)if (!ft(v, ++i, x)) return i;
return ++i;
}
/**
* Scan from right, while a test passes.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns first index where test passes till end
*/ export function scanWhileRight(x, ft) {
let a = -1, i = -1;
for (const v of x)if (!ft(v, ++i, x)) a = i;
return ++a;
}
/**
* Scan from left, until a test passes.
* @param x an array
* @param ft test function (v, i, x)
* @returns first index where test passes
*/ export function scanUntil(x, ft) {
let i = -1;
for (const v of x)if (ft(v, ++i, x)) return i;
return ++i;
}
/**
* Scan from right, until a test passes.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns first index where test fails till end
*/ export function scanUntilRight(x, ft) {
let a = -1, i = -1;
for (const v of x)if (ft(v, ++i, x)) a = i;
return ++a;
}
/**
* Find index of first value passing a test.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns first index of value, -1 if not found
*/ export function search(x, ft) {
let i = -1;
for (const v of x)if (ft(v, ++i, x)) return i;
return -1;
}
/**
* Find index of last value passing a test.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns last index of value, -1 if not found
*/ export function searchRight(x, ft) {
let i = -1, a = -1;
for (const v of x)if (ft(v, ++i, x)) a = i;
return a;
}
/**
* Find indices of values passing a test.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns indices of value
*/ export function* searchAll(x, ft) {
let i = -1;
for (const v of x)if (ft(v, ++i, x)) yield i;
}
/**
* Find first index of a value.
* @param x an iterable
* @param v search value
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first index of value, -1 if not found
*/ export function searchValue(x, v, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const v1 = fm(v, 0, null);
let i = -1;
for (const u of x){
const u1 = fm(u, ++i, x);
if (fc(u1, v1) === 0) return i;
}
return -1;
}
/**
* Find last index of a value.
* @param x an iterable
* @param v search value
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns last index of value, -1 if not found
*/ export function searchValueRight(x, v, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const v1 = fm(v, 0, null);
let i = -1, a = -1;
for (const u of x){
const u1 = fm(u, ++i, x);
if (fc(u1, v1) === 0) a = i;
}
return a;
}
/**
* Find indices of a value.
* @param x an iterable
* @param v search value
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns indices of value
*/ export function* searchValueAll(x, v, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const v1 = fm(v, 0, null);
let i = -1;
for (const u of x){
const u1 = fm(u, ++i, x);
if (fc(u1, v1) === 0) yield i;
}
}
/**
* Find first index of an infix.
* @param x an iterable
* @param y search infix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first i | x[i..i+|y|] = y else -1
*/ export function searchInfix(x, y, fc = null, fm = null) {
return head(searchInfixAll(x, y, fc, fm), -1);
}
/**
* Find last index of an infix.
* @param x an iterable
* @param y search infix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first i | x[i..i+|y|] = y else -1
*/ export function searchInfixRight(x, y, fc = null, fm = null) {
return last(searchInfixAll(x, y, fc, fm), -1);
}
/**
* Find indices of an infix.
* @param x an iterable
* @param y search infix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns i₀, i₁, ... | x[j..j+|y|] = y; j ∈ [i₀, i₁, ...]
*/ export function* searchInfixAll(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...map(y, fm)
];
const Y = y1.length;
if (Y === 0) {
yield* fromRange(0, length(x));
return;
}
const m = new Array(Y).fill(false);
let i = -1, J = 0;
for (const u of x){
const u1 = fm(u, ++i, x);
for(let j = J; j > 0; --j)m[j] = m[j - 1] && fc(u1, y1[j]) === 0;
m[0] = fc(u1, y1[0]) === 0;
J = Math.min(J + 1, Y - 1);
if (m[Y - 1]) yield i - Y + 1;
}
}
/**
* Find first index of a subsequence.
* @param x an iterable
* @param y search subsequence
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns start index of subsequence, -1 if not found
*/ export function searchSubsequence(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...map(y, fm)
];
const Y = y1.length;
if (Y === 0) return 0;
const si = [], sn = [];
let i = -1;
for (const u of x){
const u1 = fm(u, ++i, x);
const S = si.length;
for(let s = 0; s < S; ++s){
const v1 = y1[sn[s]];
if (fc(u1, v1) !== 0) continue;
if (++sn[s] === Y) return si[s];
}
const v1 = y1[0];
if (fc(u1, v1) !== 0) continue;
si.push(i);
sn.push(1);
}
return -1;
}
/**
* Check if iterable has a value.
* @param x an iterable
* @param v search value
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns v ∈ x?
*/ export function hasValue(x, v, fc = null, fm = null) {
return searchValue(x, v, fc, fm) >= 0;
}
/**
* Check if iterable starts with a prefix.
* @param x an iterable
* @param y search prefix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x[0..|y|] = y?
*/ export function hasPrefix(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const ix = x[Symbol.iterator]();
let i = -1;
for (const v of y){
const a = ix.next();
if (a.done) return false;
const u1 = fm(a.value, ++i, x);
const v1 = fm(v, i, y);
if (fc(u1, v1) !== 0) return false;
}
return true;
}
/**
* Check if iterable ends with a suffix.
* @param x an iterable
* @param y seach suffix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x[|x|-|y|..] = y?
*/ export function hasSuffix(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = Array.isArray(y) ? y : [
...y
];
const Y = y1.length;
const a = [];
let k = 0, n = 0;
if (Y === 0) return true;
for (const u of x){
a[k++ % Y] = u;
++n;
}
if (a.length < Y) return false;
for(let i = 0, j = n - Y; i < Y; ++i, ++j){
const u1 = fm(a[k++ % Y], j, x);
const v1 = fm(y1[i], i, y);
if (fc(u1, v1) !== 0) return false;
}
return true;
}
/**
* Check if iterable contains an infix.
* @param x an iterable
* @param y search infix
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x[i..I] = y for some i, I?
*/ export function hasInfix(x, y, fc = null, fm = null) {
return searchInfix(x, y, fc, fm) >= 0;
}
/**
* Check if iterable has a subsequence.
* @param x an iterable
* @param y search subsequence
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x[i₀] ⧺ x[i₁] ⧺ ... = y, for some i₀, i₁, ...? | i₀ < i₁ < ...
*/ export function hasSubsequence(x, y, fc = null, fm = null) {
return searchSubsequence(x, y, fc, fm) >= 0;
}
// FUNCTIONAL
// ----------
/**
* Call a function for each value.
* @param x an iterable
* @param fp process function (v, i, x)
*/ export function forEach(x, fp) {
let i = -1;
for (const v of x)fp(v, ++i, x);
}
/**
* Check if any value satisfies a test.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns true if ft(vᵢ) = true for some vᵢ ∈ x
*/ export function some(x, ft = null) {
if (ft) return someTest(x, ft);
else return someBoolean(x);
}
function someBoolean(x) {
for (const v of x)if (v) return true;
return false;
}
function someTest(x, ft) {
let i = -1;
for (const v of x)if (ft(v, ++i, x)) return true;
return false;
}
/**
* Check if all values satisfy a test.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns true if ft(vᵢ) = true for all vᵢ ∈ x
*/ export function every(x, ft = null) {
if (ft) return everyTest(x, ft);
else return everyBoolean(x);
}
function everyBoolean(x) {
for (const v of x)if (!v) return false;
return true;
}
function everyTest(x, ft) {
let i = -1;
for (const v of x)if (!ft(v, ++i, x)) return false;
return true;
}
/**
* Transform values of an iterable.
* @param x an iterable
* @param fm map function (v, i, x)
* @returns fm(v₀), fm(v₁), ... | vᵢ ∈ x
*/ export function* map(x, fm) {
let i = -1;
for (const v of x)yield fm(v, ++i, x);
}
/**
* Reduce values of iterable to a single value.
* @param x an iterable
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns fr(fr(acc, v₀), v₁)... | fr(acc, v₀) = v₀ if acc not given
*/ export function reduce(x, fr, acc) {
let init = arguments.length <= 2, i = -1;
for (const v of x){
if (init) {
init = false;
acc = v;
++i;
} else acc = fr(acc, v, ++i, x);
}
return acc;
}
/**
* Keep the values which pass a test.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns v₀, v₁, ... | ft(vᵢ) = true; vᵢ ∈ x
*/ export function* filter(x, ft) {
let i = -1;
for (const v of x)if (ft(v, ++i, x)) yield v;
}
export { filter as findAll };
/**
* Keep the values at given indices.
* @param x an iterable
* @param is indices (sorted)
* @returns v₀, v₁, ... | vᵢ = x[i]; i ∈ is
*/ export function* filterAt(x, is) {
let i = -1;
for (const v of x)if (is.includes(++i)) yield v;
}
/**
* Discard the values which pass a test.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns v₀, v₁, ... | ft(vᵢ) = false; vᵢ ∈ x
*/ export function* reject(x, ft) {
let i = -1;
for (const v of x)if (!ft(v, ++i, x)) yield v;
}
/**
* Discard the values at given indices.
* @param x an iterable
* @param is indices (sorted)
* @returns v₀, v₁, ... | vᵢ = x[i]; i ∉ is
*/ export function* rejectAt(x, is) {
let i = -1;
for (const v of x)if (!is.includes(++i)) yield v;
}
/**
* Produce accumulating values.
* @param x an iterable
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns fr(acc, v₀), fr(fr(acc, v₀), v₁), ... | fr(acc, v₀) = v₀ if acc not given
*/ export function* accumulate(x, fr, acc) {
let init = arguments.length <= 2, i = -1;
for (const v of x){
if (init) {
init = false;
acc = v;
++i;
} else acc = fr(acc, v, ++i, x);
yield acc;
}
}
/**
* Flatten nested iterable to given depth.
* @param x a nested iterable
* @param n maximum depth (-1 ⇒ all)
* @param fm map function (v, i, x)
* @param ft flatten test (v, i, x) [isList]
* @returns flat iterable
*/ export function* flat(x, n = -1, fm = null, ft = null) {
fm = fm || IDENTITY;
ft = ft || isList;
let i = -1;
for (const v of x){
const v1 = fm(v, ++i, x);
if (n !== 0 && ft(v1, i, x)) yield* flat(v1, n - 1, fm, ft);
else yield v1;
}
}
/**
* Flatten nested iterable, based on map function.
* @param x a nested iterable
* @param fm map function (v, i, x)
* @param ft flatten test (v, i, x) [isList]
* @returns flat iterable
*/ export function* flatMap(x, fm = null, ft = null) {
fm = fm || IDENTITY;
ft = ft || isList;
let i = -1;
for (const v of x){
const v1 = fm(v, ++i, x);
if (ft(v1, i, x)) yield* v1;
else yield v1;
}
}
/**
* Combine values from iterables.
* @param xs iterables
* @param fm map function (vs, i, xs)
* @param fe end function (dones) [some]
* @param vd default value
* @returns fm([x₀[0], x₁[0], ...]), fm([x₀[1], x₁[1], ...]), ...
*/ export function* zip(xs, fm = null, fe = null, vd) {
fm = fm || IDENTITY;
fe = fe || some;
const X = xs.length;
if (X === 0) return;
const ix = [], ds = [], vs = [];
for(let r = 0; r < X; r++)ix[r] = xs[r][Symbol.iterator]();
for(let i = 0;; ++i){
for(let r = 0; r < X; ++r){
const { done, value } = ix[r].next();
ds[r] = done;
vs[r] = done ? vd : value;
}
if (fe(ds)) break;
yield fm(vs.slice(), i, null);
}
}
// MANIPULATION
// ------------
/**
* Fill with given value.
* @param x an iterable
* @param v value
* @param i start index [0]
* @param I end index [END]
* @returns x' | x' = x; x'[i..I] = v
*/ export function* fill(x, v, i = 0, I = END) {
let j = -1;
for (const u of x){
if (++j >= i && j < I) yield v;
else yield u;
}
}
/**
* Add values to the end.
* @param x an iterable
* @param vs values to add
* @returns ...x, ...vs
*/ export function* push(x, ...vs) {
yield* x;
yield* vs;
}
/**
* Add values to the start.
* @param x an iterable
* @param vs values to add
* @returns ...vs, ...x
*/ export function* unshift(x, ...vs) {
yield* vs;
yield* x;
}
/**
* Copy part of iterable to another.
* @param x target iterable
* @param y source iterable
* @param j write index [0]
* @param i read start index [0]
* @param I read end index [END]
* @returns x[0..j] ⧺ y[i..I] ⧺ x[j+I-i..]
*/ export function* copy(x, y, j = 0, i = 0, I = END) {
let k = -1, J = -1;
for (const u of x){
if (++k === j) {
J = k;
for (const v of slice(y, i, I)){
yield v;
++J;
}
}
if (k >= j && k < J) continue;
else yield u;
}
if (k < j) {
for(; ++k < j;)yield;
yield* slice(y, i, I);
}
}
/**
* Copy part of iterable within.
* @param x an iterable
* @param j write index [0]
* @param i read start index [0]
* @param I read end index [END]
* @returns x[0..j] ⧺ x[i..I] ⧺ x[j+I-i..]
*/ export function* copyWithin(x, j = 0, i = 0, I = END) {
x = toMany(x);
let n = length(x);
for (const v of copy(x, x, j, i, I)){
if (--n < 0) break;
yield v;
}
}
// copyWithinLeft()?
// copyWithinRight()?
/**
* Move part of iterable within.
* @param x an iterable
* @param j write index [0]
* @param i read start index [0]
* @param I read end index [END]
* @returns x[0..j] ⧺ x[i..I] ⧺ x[j..i] ⧺ x[I..]
*/ export function moveWithin(x, j = 0, i = 0, I = END) {
if (j < i) return movePart(x, j, i, I);
else if (j > I) return movePart(x, i, I, j);
else return values(x);
}
function* movePart(x, j, k, l) {
const p = [];
let i = -1;
for (const v of x){
if (++i < j || i >= l) yield v;
else {
p.push(v);
if (i < l - 1) continue;
yield* p.slice(k - j);
yield* p.slice(0, k - j);
}
}
}
/**
* Remove or replaces existing values.
* @param x an iterable
* @param i remove index [0]
* @param n number of values to remove [rest]
* @param vs values to insert
* @returns x[0..i] ⧺ vs ⧺ x[i+n..]
*/ export function* splice(x, i = 0, n = END - i, ...vs) {
let j = -1;
for (const u of x){
if (++j < i || j >= i + n) yield u;
else if (j === i) yield* vs;
}
}
/**
* Break iterable considering test as separator.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns x[j..k] ⧺ x[l..m] ⧺ ... | ft(x[i]) = true; i = 0..j / k..l / ...
*/ export function* split(x, ft) {
let a = [], i = -1;
for (const v of x){
if (!ft(v, ++i, x)) a.push(v);
else if (a.length > 0) {
yield a;
a = [];
}
}
if (a.length > 0) yield a;
}
/**
* Break iterable considering indices as separator.
* @param x an iterable
* @param is indices (sorted)
* @returns x[j..k] ⧺ x[l..m] ⧺ ... | ft(x[i]) = true; i = 0..j / k..l / ...; i ∈ is
*/ export function* splitAt(x, is) {
let a = [], i = -1;
for (const v of x){
if (!is.includes(++i)) a.push(v);
else if (a.length > 0) {
yield a;
a = [];
}
}
if (a.length > 0) yield a;
}
/**
* Break iterable when test passes.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns x[0..j] ⧺ x[j..k] ⧺ ... | ft(x[i]) = true; i = j, k, ...
*/ export function* cut(x, ft) {
let i = -1, a = [];
for (const v of x){
if (ft(v, ++i, x)) {
yield a;
a = [];
}
a.push(v);
}
yield a;
}
/**
* Break iterable after test passes.
* @param x an iterable
* @param ft test function (v, i, x)
* @returns x[0..j+1] ⧺ x[j+1..k] ⧺ ... | ft(x[i]) = true; i = j, k, ...
*/ export function* cutRight(x, ft) {
let i = -1, a = [];
for (const v of x){
a.push(v);
if (ft(v, ++i, x)) {
yield a;
a = [];
}
}
yield a;
}
/**
* Break iterable at given indices.
* @param x an iterable
* @param is split indices (sorted)
* @returns x[0..j] ⧺ x[j..k] ⧺ ... | ft(x[i]) = true; i = j, k, ...; i ∈ is
*/ export function* cutAt(x, is) {
const ii = is[Symbol.iterator]();
let i = ii.next();
if (i.done) i.value = END;
let a = [], j = -1;
for (const v of x){
if (++j < i.value) {
a.push(v);
continue;
}
yield a;
a = [
v
];
i = ii.next();
if (i.done) i.value = END;
}
yield a;
for(; !i.done; i = ii.next())yield [];
}
/**
* Break iterable after given indices.
* @param x an iterable
* @param is split indices (sorted)
* @returns x[0..j+1] ⧺ x[j+1..k] ⧺ ... | ft(x[i]) = true; i = j, k, ...; i ∈ is
*/ export function* cutAtRight(x, is) {
yield* cutAt(x, map(is, (i)=>i + 1));
}
/**
* Keep similar values together and in order.
* @param x an iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x[0..k], x[k..l], ... | fc(x[i], x[j]) = 0; i, j = 0..k / k..l / ...
*/ export function* group(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
let a = [], u1 = undefined, i = -1;
for (const v of x){
const v1 = fm(v, ++i, x);
if (i > 0 && fc(u1, v1) !== 0) {
yield a;
a = [
v
];
} else a.push(v);
u1 = v1;
}
yield a;
}
/**
* Segregate values by test result.
* @param x an array
* @param ft test function (v, i, x)
* @returns [satisfies, doesnt]
*/ export function partition(x, ft) {
const t = [], f = [];
let i = -1;
for (const v of x){
if (ft(v, ++i, x)) t.push(v);
else f.push(v);
}
return [
t,
f
];
}
/**
* Segregate values by similarity.
* @param x an array
* @param fm map function (v, i, x)
* @returns Map \{key ⇒ values\}
*/ export function partitionAs(x, fm = null) {
fm = fm || IDENTITY;
const a = new Map();
let i = -1;
for (const v of x){
const v1 = fm(v, ++i, x);
if (!a.has(v1)) a.set(v1, []);
a.get(v1).push(v);
}
return a;
}
/**
* Break iterable into chunks of given size.
* @param x an iterable
* @param n chunk size [1]
* @param s chunk step [n]
* @returns x[0..n], x[s..s+n], x[2s..2s+n], ...
*/ export function* chunk(x, n = 1, s = n) {
const M = Math.max(n, s);
let m = 0, a = [];
for (const v of x){
if (m < n) a.push(v);
if (++m < M) continue;
do {
yield a;
}while (s <= 0)
a = a.slice(s);
m = a.length;
}
if (a.length > 0) yield a;
}
/**
* Obtain values that cycle through an iterable.
* @param x an iterable
* @param i start index [0]
* @param n number of values [-1 ⇒ Inf]
* @returns x[i..] ⧺ x ⧺ x ⧺ ... with upto n values
*/ export function* cycle(x, i = 0, n = -1) {
x = toMany(x);
let X = 0;
if (i < 0) {
X = length(x);
if (X === 0) return;
i = mod(i, X);
}
while(true){
X = 0;
for (const v of x){
++X;
if (--i >= 0) continue;
if (n-- === 0) return;
yield v;
}
if (X === 0) return;
if (i >= X) i = mod(i, X);
}
}
/**
* Repeat an iterable given times.
* @param x an iterable
* @param n times [-1 ⇒ Inf]
* @returns ...x, ...x, ...(n times)
*/ export function* repeat(x, n = -1) {
x = toMany(x);
for(; n !== 0; --n)yield* x;
}
/**
* Reverse the values.
* @param x an iterable
* @returns x[|x|-1], x[|x|-2], ..., x[1], x[0]
*/ export function* reverse(x) {
const a = Array.isArray(x) ? x : [
...x
];
for(let i = a.length - 1; i >= 0; --i)yield a[i];
}
/**
* Rotate values in iterable.
* @param x an iterable
* @param n rotate amount (+ve: left, -ve: right) [0]
* @returns x[n..] ⧺ x[0..n]
*/ export function rotate(x, n = 0) {
if (n === 0) return values(x);
else if (n > 0) return rotateLeft(x, n);
else return rotateRight(x, -n);
}
function* rotateLeft(x, n) {
const a = [];
let i = -1;
for (const v of x){
if (++i < n) a.push(v);
else yield v;
}
if (++i === 0 || i >= n) {
yield* a;
return;
}
n = n % i;
yield* a.slice(n);
yield* a.slice(0, n);
}
function* rotateRight(x, n) {
const a = Array.from(x);
if (a.length === 0) return;
n = n % a.length;
yield* a.slice(-n);
yield* a.slice(0, -n);
}
/**
* Place a separator between every value.
* @param x an iterable
* @param v separator
* @returns x[0], v, x[1], v, ..., x[|x|-1]
*/ export function* intersperse(x, v) {
let i = -1;
for (const u of x){
if (++i > 0) yield v;
yield u;
}
}
/**
* Estimate new values between existing ones.
* @param x an iterable
* @param fc combine function (a, b)
* @returns x[0], fc(x[0], x[1]), x[1], fc(x[1], x[2]), ..., x[|x|-1]
*/ export function* interpolate(x, fc) {
let u, i = -1;
for (const v of x){
if (++i > 0) yield fc(u, v);
yield u = v;
}
}
/**
* Place values of an iterable between another.
* @param x an iterable
* @param y another iterable
* @param m number of values from x [1]
* @param n number of values from y [1]
* @param s step size for x [m]
* @param t step size for y [n]
* @returns x[0..m], y[0..n], x[s..s+m], y[t..t+n], ..., x[k*s..|x|-1] | k ∈ W
*/ export function* intermix(x, y, m = 1, n = 1, s = m, t = n) {
const x1 = chunk(x, m, s);
const y1 = chunk(repeat(y), n, t);
const iy = y1[Symbol.iterator]();
let i = -1;
for (const u of x1){
if (++i > 0) yield* iy.next().value;
yield* u;
}
}
/**
* Place values from iterables alternately.
* @param xs iterables
* @returns x₀[0], x₁[0], ..., x₀[1], x₁[0], ... | [x₀, x₁, ...] = xs
*/ export function* interleave(xs) {
const X = xs.length;
if (X === 0) return;
const ix = [];
for(let i = 0; i < X; ++i)ix[i] = xs[i][Symbol.iterator]();
for(let i = 0, n = X; n > 0; i = (i + 1) % X){
if (ix[i] == null) continue;
const a = ix[i].next();
if (a.done) {
ix[i] = null;
--n;
} else yield a.value;
}
}
// COMBINE
// -------
/**
* Append values from iterables.
* @param xs iterables
* @returns ...x₀, ...x₁, ... | [x₀, x₁, ...] = xs
*/ export function* concat(...xs) {
for (const x of xs)yield* x;
}
/**
* Merge values from sorted iterables.
* @param xs iterables
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns sort(concat(...xs))
*/ export function* merge(xs, fc = null, fm = null) {
const X = xs.length;
const ix = [], ax = [];
let i = 0;
for(let n = 0; n < X; ++n){
ix[i] = xs[i][Symbol.iterator]();
ax[i] = ix[i].next();
if (!ax[i].done) ++i;
}
while(i > 0){
const as = ax.map((a)=>a.value);
const j = minEntry(as, fc, fm)[0];
yield as[j];
ax[j] = ix[j].next();
if (!ax[j].done) continue;
ix.splice(j, 1);
ax.splice(j, 1);
--i;
}
}
/**
* Join values together into a string.
* @param x an iterable
* @param sep separator [,]
* @returns "$\{v₀\}$\{sep\}$\{v₁\}..." | vᵢ ∈ x
*/ export function join(x, sep = ",") {
let a = "";
for (const v of x)a += v + sep;
return a.substring(0, a.length - sep.length);
}
// SET OPERATIONS
// --------------
/**
* Check if there are no duplicate values.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns ∀ vᵢ, vⱼ ∈ x, is vᵢ ≠ vⱼ?
*/ export function isUnique(x, fc = null, fm = null) {
if (fc) return isUniqueDual(x, fc, fm);
else return isUniqueMap(x, fm);
}
function isUniqueMap(x, fm = null) {
fm = fm || IDENTITY;
const x1 = new Set();
let i = -1;
for (const v of x){
const v1 = fm(v, ++i, x);
if (x1.has(v1)) return false;
x1.add(v1);
}
return true;
}
function isUniqueDual(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const x1 = [
...map(x, fm)
];
for (const u1 of x1){
for (const v1 of x1)if (fc(u1, v1) === 0) return false;
}
return true;
}
/**
* Checks if arrays have no value in common.
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x ∩ y = Φ?
*/ export function isDisjoint(x, y, fc = null, fm = null) {
if (fc) return isDisjointDual(x, y, fc, fm);
else return isDisjointMap(x, y, fm);
}
function isDisjointMap(x, y, fm = null) {
const y1 = toSet(y, fm);
let i = -1;
fm = fm || IDENTITY;
for (const u of x){
const u1 = fm(u, ++i, x);
if (y1.has(u1)) return false;
}
return true;
}
function isDisjointDual(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...map(y, fm)
];
let i = -1;
for (const u of x){
const u1 = fm(u, ++i, x);
for (const v1 of y1)if (fc(u1, v1) === 0) return false;
}
return true;
}
/**
* Remove duplicate values.
* @param x an iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns v₀, v₁, ... | vᵢ ∈ x; vᵢ ≠ vⱼ ∀ i, j
*/ export function* unique(x, fc = null, fm = null) {
if (fc) yield* uniqueDual(x, fc, fm);
else yield* uniqueMap(x, fm);
}
function* uniqueMap(x, fm = null) {
fm = fm || IDENTITY;
const x1 = new Set();
let i = -1;
for (const v of x){
const v1 = fm(v, ++i, x);
if (x1.has(v1)) continue;
x1.add(v1);
yield v;
}
}
function* uniqueDual(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const x1 = [];
let i = -1;
NEXTX: for (const v of x){
const v1 = fm(v, ++i, x);
for (const u1 of x1)if (fc(u1, v1) === 0) continue NEXTX;
x1.push(v1);
yield v;
}
}
/**
* Obtain values present in any iterable.
* @param x an iterable
* @param y another iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x ∪ y = \{v | v ∈ x or v ∈ y\}
*/ export function* union(x, y, fc = null, fm = null) {
if (fc) yield* unionDual(x, y, fc, fm);
else yield* unionMap(x, y, fm);
}
function* unionMap(x, y, fm = null) {
fm = fm || IDENTITY;
const x1 = new Set();
let i = -1, j = -1;
for (const u of x){
const u1 = fm(u, ++i, x);
x1.add(u1);
yield u;
}
for (const v of y){
const v1 = fm(v, ++j, y);
if (!x1.has(v1)) yield v;
}
}
function* unionDual(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
x = toMany(x);
yield* x;
const x1 = [
...map(x, fm)
];
let j = -1;
NEXTY: for (const v of y){
const v1 = fm(v, ++j, y);
for (const u1 of x1)if (fc(u1, v1) === 0) continue NEXTY;
yield v;
}
}
/**
* Obtain values present in both iterables.
* @param x an iterable
* @param y another iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x ∩ y = \{v | v ∈ x, v ∈ y\}
*/ export function* intersection(x, y, fc = null, fm = null) {
if (fc) yield* intersectionDual(x, y, fc, fm);
else yield* intersectionMap(x, y, fm);
}
function* intersectionMap(x, y, fm = null) {
const y1 = toSet(y, fm);
let i = -1;
fm = fm || IDENTITY;
for (const u of x){
const u1 = fm(u, ++i, x);
if (y1.has(u1)) yield u;
}
}
function* intersectionDual(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...map(y, fm)
];
let i = -1;
NEXTX: for (const u of x){
const u1 = fm(u, ++i, x);
for (const v1 of y1)if (fc(u1, v1) === 0) {
yield u;
continue NEXTX;
}
}
}
/**
* Obtain values not present in another iterable.
* @param x an iterable
* @param y another iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x - y = \{v | v ∈ x, v ∉ y\}
*/ export function* difference(x, y, fc = null, fm = null) {
if (fc) yield* differenceDual(x, y, fc, fm);
else yield* differenceMap(x, y, fm);
}
function* differenceMap(x, y, fm = null) {
const y1 = toSet(y, fm);
let i = -1;
fm = fm || IDENTITY;
for (const u of x){
const u1 = fm(u, ++i, x);
if (!y1.has(u1)) yield u;
}
}
function* differenceDual(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...map(y, fm)
];
let i = -1;
NEXTX: for (const u of x){
const u1 = fm(u, ++i, x);
for (const v1 of y1)if (fc(u1, v1) === 0) continue NEXTX;
yield u;
}
}
/**
* Obtain values not present in both iterables.
* @param x an iterable
* @param y another iterable
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x-y ∪ y-x
*/ export function* symmetricDifference(x, y, fc = null, fm = null) {
x = toMany(x);
y = toMany(y);
yield* difference(x, y, fc, fm);
yield* difference(y, x, fc, fm);
}
/**
* List cartesian product of iterables.
* @param xs iterables
* @param fm map function (vs, i)
* @returns x₀ × x₁ × ... = \{[v₀, v₁, ...] | v₀ ∈ x₀, v₁ ∈ x₁, ...] \}
*/ export function* cartesianProduct(xs, fm = null) {
fm = fm || IDENTITY;
const X = xs.length;
if (X === 0) return;
const jx = [], ix = [], ax = [];
for(let i = 0; i < X; ++i){
jx[i] = i > 0 ? toMany(xs[i]) : xs[i];
ix[i] = jx[i][Symbol.iterator]();
ax[i] = ix[i].next();
if (ax[i].done) return;
}
for(let i = 0;; ++i){
const vs = [];
for (const a of ax)vs.push(a.value);
yield fm(vs, i, null);
let r = X - 1;
for(; r >= 0; --r){
ax[r] = ix[r].next();
if (!ax[r].done) break;
ix[r] = jx[r][Symbol.iterator]();
ax[r] = ix[r].next();
}
if (r < 0) break;
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9leHRyYS1pdGVyYWJsZS9leHRyYS1pdGVyYWJsZS9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0lERU5USVRZLCBDT01QQVJFfSBmcm9tIFwiQG5vZGVmL2V4dHJhLWZ1bmN0aW9uXCI7XG5pbXBvcnQge21vZH0gZnJvbSBcIkBub2RlZi9leHRyYS1tYXRoXCI7XG5cblxuXG5cbi8vIENPTlNUQU5UU1xuLy8gPT09PT09PT09XG5cbi8qKiBFbmQgb2YgaXRlcmFibGUuICovXG5leHBvcnQgY29uc3QgRU5EID0gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVI7XG5cbi8qKiBFbXB0eSBpdGVyYWJsZS4gKi9cbmNvbnN0IEVNUFRZID0gW10udmFsdWVzKCk7XG5cblxuXG5cbi8vIFRZUEVTXG4vLyA9PT09PVxuXG4vKipcbiAqIEhhbmRsZSByZWFkaW5nIG9mIGEgc2luZ2xlIHZhbHVlLlxuICogQHJldHVybnMgdmFsdWVcbiAqL1xuZXhwb3J0IHR5cGUgUmVhZEZ1bmN0aW9uPFQ+ID0gKCkgPT4gVDtcblxuXG4vKipcbiAqIEhhbmRsZSBjb21iaW5pbmcgb2YgdHdvIHZhbHVlcy5cbiAqIEBwYXJhbSBhIGEgdmFsdWVcbiAqIEBwYXJhbSBiIGFub3RoZXIgdmFsdWVcbiAqIEByZXR1cm5zIGNvbWJpbmVkIHZhbHVlXG4gKi9cbmV4cG9ydCB0eXBlIENvbWJpbmVGdW5jdGlvbjxUPiA9IChhOiBULCBiOiBUKSA9PiBUO1xuXG5cbi8qKlxuICogSGFuZGxlIGNvbXBhcmlzb24gb2YgdHdvIHZhbHVlcy5cbiAqIEBwYXJhbSBhIGEgdmFsdWVcbiAqIEBwYXJhbSBiIGFub3RoZXIgdmFsdWVcbiAqIEByZXR1cm5zIGE8YjogLXZlLCBhPWI6IDAsIGE+YjogK3ZlXG4gKi9cbmV4cG9ydCB0eXBlIENvbXBhcmVGdW5jdGlvbjxUPiA9IChhOiBULCBiOiBUKSA9PiBudW1iZXI7XG5cblxuLyoqXG4gKiBIYW5kbGUgcHJvY2Vzc2luZyBvZiB2YWx1ZXMgaW4gYW4gaXRlcmFibGUuXG4gKiBAcGFyYW0gdiB2YWx1ZSBpbiBpdGVyYWJsZVxuICogQHBhcmFtIGkgaW5kZXggb2YgdmFsdWUgaW4gaXRlcmFibGVcbiAqIEBwYXJhbSB4IGl0ZXJhYmxlIGNvbnRhaW5pbmcgdGhlIHZhbHVlXG4gKi9cbmV4cG9ydCB0eXBlIFByb2Nlc3NGdW5jdGlvbjxUPiA9ICh2OiBULCBpOiBudW1iZXIsIHg6IEl0ZXJhYmxlPFQ+KSA9PiB2b2lkO1xuXG5cbi8qKlxuICogSGFuZGxlIHNlbGVjdGlvbiBvZiB2YWx1ZXMgaW4gYW4gaXRlcmFibGUuXG4gKiBAcGFyYW0gdiB2YWx1ZSBpbiBpdGVyYWJsZVxuICogQHBhcmFtIGkgaW5kZXggb2YgdmFsdWUgaW4gaXRlcmFibGVcbiAqIEBwYXJhbSB4IGl0ZXJhYmxlIGNvbnRhaW5pbmcgdGhlIHZhbHVlXG4gKiBAcmV0dXJucyBzZWxlY3RlZD9cbiAqL1xuZXhwb3J0IHR5cGUgVGVzdEZ1bmN0aW9uPFQ+ID0gKHY6IFQsIGk6IG51bWJlciwgeDogSXRlcmFibGU8VD4pID0+IGJvb2xlYW47XG5cblxuLyoqXG4gKiBIYW5kbGUgdHJhbnNmb3JtYXRpb24gb2YgYSB2YWx1ZSB0byBhbm90aGVyLlxuICogQHBhcmFtIHYgdmFsdWUgaW4gaXRlcmFibGVcbiAqIEBwYXJhbSBpIGluZGV4IG9mIHZhbHVlIGluIGl0ZXJhYmxlXG4gKiBAcGFyYW0geCBpdGVyYWJsZSBjb250YWluaW5nIHRoZSB2YWx1ZVxuICogQHJldHVybnMgdHJhbnNmb3JtZWQgdmFsdWVcbiAqL1xuZXhwb3J0IHR5cGUgTWFwRnVuY3Rpb248VCwgVT4gPSAodjogVCwgaTogbnVtYmVyLCB4OiBJdGVyYWJsZTxUPiB8IG51bGwpID0+IFU7XG5cblxuLyoqXG4gKiBIYW5kbGUgcmVkdWN0aW9uIG9mIG11bHRpcGxlIHZhbHVlcyBpbnRvIGEgc2luZ2xlIHZhbHVlLlxuICogQHBhcmFtIGFjYyBhY2N1bXVsYXRvciAodGVtcG9yYXJ5IHJlc3VsdClcbiAqIEBwYXJhbSB2IHZhbHVlIGluIGl0ZXJhYmxlXG4gKiBAcGFyYW0gaSBpbmRleCBvZiB2YWx1ZSBpbiBpdGVyYWJsZVxuICogQHBhcmFtIHggaXRlcmFibGUgY29udGFpbmluZyB0aGUgdmFsdWVcbiAqIEByZXR1cm5zIHJlZHVjZWQgdmFsdWVcbiAqL1xuZXhwb3J0IHR5cGUgUmVkdWNlRnVuY3Rpb248VCwgVT4gPSAoYWNjOiBVLCB2OiBULCBpOiBudW1iZXIsIHg6IEl0ZXJhYmxlPFQ+KSA9PiBVO1xuXG5cbi8qKlxuICogSGFuZGxlIGVuZGluZyBvZiBhIGNvbWJpbmVkIGl0ZXJhYmxlLlxuICogQHBhcmFtIGRvbmVzIGnhtZfKsCBpdGVyYWJsZSBkb25lP1xuICogQHJldHVybnMgY29tYmluZWQgaXRlcmFibGUgZG9uZT9cbiAqL1xuZXhwb3J0IHR5cGUgRW5kRnVuY3Rpb24gPSAoZG9uZXM6IGJvb2xlYW5bXSkgPT4gYm9vbGVhbjtcblxuXG5cblxuLy8gTUVUSE9EU1xuLy8gPT09PT09PVxuXG4vLyBIRUxQRVJTXG4vLyAtLS0tLS0tXG5cbi8qKiBDb252ZXJ0IGFuIGl0ZXJhYmxlIHRvIHNldC4gKi9cbmZ1bmN0aW9uIHRvU2V0PFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIGZtOiBNYXBGdW5jdGlvbjxULCBVPiB8IG51bGw9bnVsbCk6IFNldDxUfFU+IHtcbiAgaWYgKCFmbSkgcmV0dXJuIG5ldyBTZXQoeCk7XG4gIGNvbnN0IGEgPSBuZXcgU2V0PFU+KCk7IGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGEuYWRkKGZtKHYsICsraSwgeCkpO1xuICByZXR1cm4gYTtcbn1cblxuXG5cblxuLy8gQUJPVVRcbi8vIC0tLS0tXG5cbi8qKlxuICogQ2hlY2sgaWYgdmFsdWUgaXMgYW4gaXRlcmFibGUuXG4gKiBAcGFyYW0gdiBhIHZhbHVlXG4gKiBAcmV0dXJucyB2IGlzIGl0ZXJhYmxlP1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXModjogdW5rbm93bik6IHYgaXMgSXRlcmFibGU8dW5rbm93bj4ge1xuICByZXR1cm4gdiAhPSBudWxsICYmIHR5cGVvZiAodiBhcyBJdGVyYWJsZTx1bmtub3duPilbU3ltYm9sLml0ZXJhdG9yXSA9PT0gXCJmdW5jdGlvblwiO1xufVxuXG5cbi8qKlxuICogQ2hlY2sgaWYgdmFsdWUgaXMgYW4gaXRlcmF0b3IuXG4gKiBAcGFyYW0gdiBhIHZhbHVlXG4gKiBAcmV0dXJucyB2IGltcGxlbWVudHMgXFx7bmV4dCgpLCByZXR1cm4/KCksIHRocm93PygpXFx9P1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNJdGVyYXRvcih2OiB1bmtub3duKTogdiBpcyBJdGVyYXRvcjx1bmtub3duPiB7XG4gIHJldHVybiB2ICE9IG51bGwgJiYgdHlwZW9mICh2IGFzIEl0ZXJhdG9yPHVua25vd24+KS5uZXh0ID09PSBcImZ1bmN0aW9uXCI7XG59XG5cblxuLyoqXG4gKiBDaGVjayBpZiB2YWx1ZSBpcyBhIGxpc3QgKGl0ZXJhYmxlICYgIXN0cmluZykuXG4gKiBAcGFyYW0gdiBhIHZhbHVlXG4gKiBAcmV0dXJucyB2IGlzIGxpc3Q/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0xpc3Q8VD4odjogSXRlcmFibGU8VD4pOiBib29sZWFuIHtcbiAgcmV0dXJuIGlzKHYpICYmIHR5cGVvZiB2IT09XCJzdHJpbmdcIjtcbn1cblxuXG4vKipcbiAqIEdldCBpdGVyYXRvciBvZiBhbiBpdGVyYWJsZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcmV0dXJucyB4XFxbXFw8aXRlcmF0b3JcXD5cXF0oKVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXRlcmF0b3I8VD4oeDogSXRlcmFibGU8VD4pOiBJdGVyYXRvcjxUPiB7XG4gIHJldHVybiB4W1N5bWJvbC5pdGVyYXRvcl0oKTtcbn1cblxuXG4vKipcbiAqIExpc3QgYWxsIGluZGljZXMuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHJldHVybnMgMCwgMSwgLi4uLCB8eHwtMVxuICovXG5leHBvcnQgZnVuY3Rpb24qIGtleXM8VD4oeDogSXRlcmFibGU8VD4pOiBJdGVyYWJsZUl0ZXJhdG9yPG51bWJlcj4ge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IF8gb2YgeClcbiAgICB5aWVsZCArK2k7XG59XG5cblxuLyoqXG4gKiBMaXN0IGFsbCB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHJldHVybnMgduKCgCwgduKCgSwgLi4uIHwgduG1oiA9IHhbaV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiB2YWx1ZXM8VD4oeDogSXRlcmFibGU8VD4pOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgeWllbGQqIHg7XG59XG5leHBvcnQge3ZhbHVlcyBhcyB0b09uY2V9O1xuXG5cbi8qKlxuICogTGlzdCBhbGwgaW5kZXgtdmFsdWUgcGFpcnMuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHJldHVybnMgWzAsIHbigoBdLCBbMSwgduKCgV0sIC4uLiB8IHbhtaIgPSB4W2ldXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogZW50cmllczxUPih4OiBJdGVyYWJsZTxUPik6IEl0ZXJhYmxlSXRlcmF0b3I8W251bWJlciwgVF0+IHtcbiAgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgeWllbGQgWysraSwgdl07XG59XG5cblxuXG5cbi8vIEdFTkVSQVRFXG4vLyAtLS0tLS0tLVxuXG4vKipcbiAqIENvbnZlcnQgYW4gaXRlcmFibGUtbGlrZSB0byBpdGVyYWJsZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhdG9yL2l0ZXJhYmxlXG4gKiBAcmV0dXJucyB4IGFzIGl0ZXJhYmxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmcm9tPFQ+KHg6IEl0ZXJhdG9yPFQ+IHwgSXRlcmFibGU8VD4pOiBJdGVyYWJsZTxUPiB7XG4gIGlmIChpcyh4KSkgcmV0dXJuIHg7XG4gIHJldHVybiBmcm9tSXRlcmF0b3IoeCk7XG59XG5cblxuLyoqXG4gKiBDb252ZXJ0IGFuIGl0ZXJhdG9yIHRvIGl0ZXJhYmxlLlxuICogQHBhcmFtIHggYW4gaXRlcmF0b3IvaXRlcmFibGVcbiAqIEByZXR1cm5zIHggYXMgaXRlcmFibGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZyb21JdGVyYXRvcjxUPih4OiBJdGVyYXRvcjxUPik6IEl0ZXJhYmxlPFQ+IHtcbiAgcmV0dXJuIHtbU3ltYm9sLml0ZXJhdG9yXTogKCkgPT4geH07XG59XG5cblxuLyoqXG4gKiBHZW5lcmF0ZSBpdGVyYWJsZSBmcm9tIGdpdmVuIG51bWJlciByYW5nZS5cbiAqIEBwYXJhbSB2IHN0YXJ0IG51bWJlciBbMF1cbiAqIEBwYXJhbSBWIHN0b3AgbnVtYmVyLCBleGNsdWRpbmcgW0VORF1cbiAqIEBwYXJhbSBkdiBzdGVwIHNpemUgWzFdXG4gKiBAcmV0dXJucyB2LCB2K2R2LCB2KzJkdiwgLi4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogZnJvbVJhbmdlKHY6IG51bWJlcj0wLCBWOiBudW1iZXI9RU5ELCBkdjogbnVtYmVyPTEpOiBJdGVyYWJsZUl0ZXJhdG9yPG51bWJlcj4ge1xuICBjb25zdCBOID0gKFYtdikgLyBkdjtcbiAgZm9yIChsZXQgbj0wOyBuPE47ICsrbiwgdis9ZHYpXG4gICAgeWllbGQgdjtcbn1cblxuXG4vKipcbiAqIEdlbmVyYXRlIGl0ZXJhYmxlIGZyb20gcmVwZWF0ZWQgZnVuY3Rpb24gaW52b2NhdGlvbi5cbiAqIEBwYXJhbSBmbiBmdW5jdGlvbiAoaW1wdXJlKVxuICogQHBhcmFtIGFyZ3MgYXJndW1lbnRzXG4gKiBAcmV0dXJucyBmbiguLi5hcmdzKSwgZm4oLi4uYXJncyksIC4uLlxuICovXG5leHBvcnQgZnVuY3Rpb24qIGZyb21JbnZvY2F0aW9uPFQsIEEgZXh0ZW5kcyB1bmtub3duW10gPSB1bmtub3duW10+KGZuOiAoLi4uYXJnczogQSkgPT4gVCwgLi4uYXJnczogQSk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBmb3IgKDs7KVxuICAgIHlpZWxkIGZuKC4uLmFyZ3MpO1xufVxuZXhwb3J0IHtmcm9tSW52b2NhdGlvbiBhcyBmcm9tQ2FsbH07XG5cblxuLyoqXG4gKiBHZW5lcmF0ZSBpdGVyYWJsZSBmcm9tIHJlcGVhdGVkIGZ1bmN0aW9uIGFwcGxpY2F0aW9uLlxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSlcbiAqIEBwYXJhbSB2IHN0YXJ0IHZhbHVlXG4gKiBAcmV0dXJucyB2LCBmbSh2KSwgZm0oZm0odikpLCAuLi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBmcm9tQXBwbGljYXRpb248VD4oZm06IE1hcEZ1bmN0aW9uPFQsIFQ+LCB2OiBUKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIHlpZWxkIHY7XG4gIGZvciAobGV0IGk9MTs7ICsraSlcbiAgICB5aWVsZCB2ID0gZm0odiwgaSwgbnVsbCk7XG59XG5leHBvcnQge2Zyb21BcHBsaWNhdGlvbiBhcyBmcm9tQXBwbHl9O1xuXG5cblxuXG4vLyBCRUhBVklPUlxuLy8gLS0tLS0tLS1cblxuLyoqXG4gKiBDaGVjayBpZiBhbiBpdGVyYWJsZSBjYW4gaXRlcmF0ZWQgb25seSBvbmNlLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEByZXR1cm5zIHhcXFtcXDxpdGVyYXRvclxcPlxcXSA9IHg/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc09uY2U8VD4oeDogSXRlcmFibGU8VD4pOiB4IGlzIEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICByZXR1cm4geFtTeW1ib2wuaXRlcmF0b3JdKCk9PT0oeCBhcyB1bmtub3duKTtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIGFuIGl0ZXJhYmxlIGNhbiBiZSBpdGVyYXRlZCBtYW55IHRpbWVzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEByZXR1cm5zIHhcXFtcXDxpdGVyYXRvclxcPlxcXSDiiaAgeD9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzTWFueTxUPih4OiBJdGVyYWJsZTxUPik6IHggaXMgSXRlcmFibGU8VD4ge1xuICByZXR1cm4gIWlzT25jZSh4KTtcbn1cblxuXG4vKipcbiAqIENvbnZlcnQgYSBvbmNlLWxpa2UgaXRlcmFibGUgdG8gbWFueS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gbm93IGNvbnN1bWUgaW1tZWRpYXRlbHk/IFtmYWxzZV1cbiAqIEByZXR1cm5zIHgnIHwgeCcgPSB4OyB4JyBjYW4gYmUgaXRlcmF0ZWQgbXVsdGlwbGUgdGltZXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvTWFueTxUPih4OiBJdGVyYWJsZTxUPiwgbm93OiBib29sZWFuPWZhbHNlKTogSXRlcmFibGU8VD4ge1xuICBpZiAoIWlzT25jZSh4KSkgcmV0dXJuIHg7XG4gIHJldHVybiBub3c/IEFycmF5LmZyb20oeCkgOiB0b01hbnlMYXRlKHhbU3ltYm9sLml0ZXJhdG9yXSgpLCBbXSk7XG59XG5leHBvcnQge3RvTWFueSBhcyBtYW55fTtcblxuZnVuY3Rpb24gdG9NYW55TGF0ZTxUPihpeDogSXRlcmF0b3I8VD4sIGE6IFRbXSk6IEl0ZXJhYmxlPFQ+IHtcbiAgcmV0dXJuIHtcbiAgICBbU3ltYm9sLml0ZXJhdG9yXTogKCkgPT4ge1xuICAgICAgbGV0IGkgPSAtMTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5leHQ6ICgpID0+IHtcbiAgICAgICAgICBpZiAoKytpIDwgYS5sZW5ndGgpIHJldHVybiB7dmFsdWU6IGFbaV0sIGRvbmU6IGZhbHNlfTtcbiAgICAgICAgICBjb25zdCB7dmFsdWUsIGRvbmV9ID0gaXgubmV4dCgpO1xuICAgICAgICAgIGlmICghZG9uZSkgICBhW2ldID0gdmFsdWU7XG4gICAgICAgICAgcmV0dXJuIHt2YWx1ZSwgZG9uZX07XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgfVxuICB9O1xufVxuXG5cbi8qKlxuICogR2VuZXJhdGUgYSBmdW5jdGlvbiB0aGF0IGl0ZXJhdGVzIG92ZXIgdmFsdWVzIHVwb24gaW52b2NhdGlvbi5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcmV0dXJucyBmbiB8IGZuKCkg4oaSIHhbMF0sIGZuKCkg4oaSIHhbMV0sIC4uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9JbnZva2FibGU8VD4oeDogSXRlcmFibGU8VD4pOiAoKSA9PiBUIHtcbiAgY29uc3QgaXggPSB4W1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgcmV0dXJuICgpID0+IGl4Lm5leHQoKS52YWx1ZTtcbn1cbmV4cG9ydCB7dG9JbnZva2FibGUgYXMgdG9DYWxsYWJsZX07XG5leHBvcnQge3RvSW52b2thYmxlIGFzIGNhbGxhYmxlfTtcblxuXG5cblxuLy8gTEVOR1RIXG4vLyAtLS0tLS1cblxuLyoqXG4gKiBDaGVjayBpZiBhbiBpdGVyYWJsZSBpcyBlbXB0eS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcmV0dXJucyB8eHwgPSAwP1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNFbXB0eTxUPih4OiBJdGVyYWJsZTxUPik6IGJvb2xlYW4ge1xuICBmb3IgKGNvbnN0IF8gb2YgeClcbiAgICByZXR1cm4gZmFsc2U7XG4gIHJldHVybiB0cnVlO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgbGVuZ3RoIG9mIGFuIGl0ZXJhYmxlLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBpIHN0YXJ0IGluZGV4IFswXVxuICogQHBhcmFtIEkgZW5kIGluZGV4IFtFTkRdXG4gKiBAcmV0dXJucyB8eFtpLi5JXXxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxlbmd0aDxUPih4OiBJdGVyYWJsZTxUPiwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj1FTkQpOiBudW1iZXIge1xuICBsZXQgaiA9IC0xLCBuID0gMDtcbiAgZm9yIChjb25zdCBfIG9mIHgpXG4gICAgaWYgKCsraj49aSAmJiBqPEkpICsrbjtcbiAgcmV0dXJuIG47XG59XG5leHBvcnQge2xlbmd0aCBhcyBzaXplfTtcblxuXG4vKipcbiAqIEdldCB6ZXJvLWJhc2VkIGluZGV4IGZvciBlbGVtZW50IGluIGl0ZXJhYmxlLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBpIGluZGV4ICgtdmU6IGZyb20gcmlnaHQpXG4gKiBAcmV0dXJucyBpJyB8IHhbaSddID0geFtpXTsgaScg4oiIIFswLCB8eHxdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmRleDxUPih4OiBJdGVyYWJsZTxUPiwgaTogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgWCA9IGxlbmd0aCh4KTtcbiAgcmV0dXJuIGk+PTA/IE1hdGgubWluKGksIFgpIDogTWF0aC5tYXgoWCtpLCAwKTtcbn1cblxuXG4vKipcbiAqIEdldCBpbmRleCByYW5nZSBmb3IgcGFydCBvZiBpdGVyYWJsZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gaSBzdGFydCBpbmRleCAoLXZlOiBmcm9tIHJpZ2h0KSBbMF1cbiAqIEBwYXJhbSBJIGVuZCBpbmRleCAoLXZlOiBmcm9tIHJpZ2h0KSBbRU5EXVxuICogQHJldHVybnMgW2knLCBJJ10gfCBpJyDiiaQgSSc7IGknLCBJJyDiiIggWzAsIHx4fF1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluZGV4UmFuZ2U8VD4oeDogSXRlcmFibGU8VD4sIGk6IG51bWJlcj0wLCBJOiBudW1iZXI9RU5EKTogW251bWJlciwgbnVtYmVyXSB7XG4gIGNvbnN0IFggPSBsZW5ndGgoeCk7XG4gIGkgPSBpPj0wPyBNYXRoLm1pbihpLCBYKSA6IE1hdGgubWF4KFgraSwgMCk7XG4gIEkgPSBJPj0wPyBNYXRoLm1pbihJLCBYKSA6IE1hdGgubWF4KFgrSSwgMCk7XG4gIHJldHVybiBbaSwgTWF0aC5tYXgoaSwgSSldO1xufVxuXG5cblxuXG4vLyBDT01QQVJFXG4vLyAtLS0tLS0tXG5cbi8qKlxuICogQ29tcGFyZSB0d28gaXRlcmFibGVzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSB5IGFub3RoZXIgaXRlcmFibGVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHg8eTogLTEsIHg9eTogMCwgeD55OiAxXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb21wYXJlPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIHk6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBpeCA9IHhbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICBjb25zdCBpeSA9IHlbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICBsZXQgdSwgdjtcbiAgZm9yIChsZXQgaT0wOzsgKytpKSB7XG4gICAgdSA9IGl4Lm5leHQoKTtcbiAgICB2ID0gaXkubmV4dCgpO1xuICAgIGlmICh1LmRvbmUgfHwgdi5kb25lKSBicmVhaztcbiAgICBjb25zdCB1MSA9IGZtKHUudmFsdWUsIGksIHgpO1xuICAgIGNvbnN0IHYxID0gZm0odi52YWx1ZSwgaSwgeSk7XG4gICAgY29uc3QgYyAgPSBmYyh1MSwgdjEpO1xuICAgIGlmIChjIT09MCkgcmV0dXJuIGM7XG4gIH1cbiAgcmV0dXJuICh2LmRvbmU/IDE6MCkgLSAodS5kb25lPyAxOjApO1xufVxuXG5cbi8qKlxuICogQ2hlY2sgaWYgdHdvIGl0ZXJhYmxlcyBhcmUgZXF1YWwuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIHkgYW5vdGhlciBpdGVyYWJsZVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeD15P1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNFcXVhbDxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCB5OiBJdGVyYWJsZTxUPiwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICByZXR1cm4gY29tcGFyZSh4LCB5LCBmYywgZm0pPT09MDtcbn1cblxuXG5cblxuLy8gR0VUL1NFVFxuLy8gLS0tLS0tLVxuXG4vKipcbiAqIEdldCB2YWx1ZSBhdCBpbmRleC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gaSBpbmRleFxuICogQHJldHVybnMgeFtpXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0PFQ+KHg6IEl0ZXJhYmxlPFQ+LCBpOiBudW1iZXIpOiBUIHwgdW5kZWZpbmVkIHtcbiAgbGV0IGogPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgaWYgKCsraj09PWkpIHJldHVybiB2O1xufVxuXG5cbi8qKlxuICogR2V0IHZhbHVlcyBhdCBpbmRpY2VzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBpcyBpbmRpY2VzIChzb3J0ZWQpXG4gKiBAcmV0dXJucyB4W2nigoBdLCB4W2nigoFdLCAuLi4gfCBbaeKCgCwgaeKCgSwgLi4uXSA9IGlzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogZ2V0QWxsPFQ+KHg6IEl0ZXJhYmxlPFQ+LCBpczogbnVtYmVyW10pOiBJdGVyYWJsZUl0ZXJhdG9yPFQgfCB1bmRlZmluZWQ+IHtcbiAgbGV0ICAgaSAgPSAwLCBqID0gLTE7XG4gIGNvbnN0IElTID0gaXMubGVuZ3RoO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmIChpc1tpXSE9PSsraikgY29udGludWU7XG4gICAgZG8geyB5aWVsZCB2OyB9ICB3aGlsZSAoKytpPElTICYmIGlzW2ldPT09aXNbaS0xXSk7XG4gICAgaWYgKGk+PUlTKSBicmVhaztcbiAgfVxuICBmb3IgKDsgaTxJUzsgKytpKVxuICAgIHlpZWxkO1xufVxuXG5cbi8qKlxuICogR2V0IHZhbHVlIGF0IHBhdGggaW4gYSBuZXN0ZWQgaXRlcmFibGUuXG4gKiBAcGFyYW0geCBhIG5lc3RlZCBpdGVyYWJsZVxuICogQHBhcmFtIHAgcGF0aFxuICogQHJldHVybnMgeFtp4oKAXVtp4oKBXVsuLi5dIHwgW2nigoAsIGnigoEsIC4uLl0gPSBwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRQYXRoKHg6IEl0ZXJhYmxlPHVua25vd24+LCBwOiBudW1iZXJbXSk6IHVua25vd24ge1xuICBsZXQgeGFueTogdW5rbm93biA9IHg7XG4gIGZvciAoY29uc3QgaSBvZiBwKVxuICAgIHhhbnkgPSBpcyh4YW55KT8gZ2V0KHhhbnksIGkpIDogdW5kZWZpbmVkO1xuICByZXR1cm4geGFueTtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIG5lc3RlZCBpdGVyYWJsZSBoYXMgYSBwYXRoLlxuICogQHBhcmFtIHggYSBuZXN0ZWQgaXRlcmFibGVcbiAqIEBwYXJhbSBwIHBhdGhcbiAqIEByZXR1cm5zIHhbaeKCgF1baeKCgV1bLi4uXSBleGlzdHM/IHwgW2nigoAsIGnigoEsIC4uLl0gPSBwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNQYXRoKHg6IEl0ZXJhYmxlPHVua25vd24+LCBwOiBudW1iZXJbXSk6IGJvb2xlYW4ge1xuICByZXR1cm4gZ2V0UGF0aCh4LCBwKSE9PXVuZGVmaW5lZDtcbn1cblxuXG4vKipcbiAqIFNldCB2YWx1ZSBhdCBpbmRleC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gaSBpbmRleFxuICogQHBhcmFtIHYgdmFsdWVcbiAqIEByZXR1cm5zIHgnIHwgeCcgPSB4OyB4J1tpXSA9IHZcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBzZXQ8VD4oeDogSXRlcmFibGU8VD4sIGk6IG51bWJlciwgdjogVCk6IEl0ZXJhYmxlSXRlcmF0b3I8VCB8IHVuZGVmaW5lZD4ge1xuICBsZXQgaiA9IC0xO1xuICBmb3IgKGNvbnN0IHUgb2YgeClcbiAgICB5aWVsZCArK2o9PT1pPyB2IDogdTtcbiAgaWYgIChqPj1pKSByZXR1cm47XG4gIGZvciAoOyArK2o8aTspIHlpZWxkO1xuICB5aWVsZCB2O1xufVxuXG5cbi8qKlxuICogRXhjaGFuZ2UgdHdvIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gaSBhbiBpbmRleFxuICogQHBhcmFtIGogYW5vdGhlciBpbmRleFxuICogQHJldHVybnMgeCcgfCB4JyA9IHg7IHgnW2ldID0geFtqXTsgeCdbal0gPSB4W2ldXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogc3dhcDxUPih4OiBJdGVyYWJsZTxUPiwgaTogbnVtYmVyLCBqOiBudW1iZXIpOiBJdGVyYWJsZUl0ZXJhdG9yPFQgfCB1bmRlZmluZWQ+IHtcbiAgaWYgKGk9PT1qKSB7IHlpZWxkKiB4OyByZXR1cm47IH1cbiAgY29uc3QgayA9IE1hdGgubWluKGksIGopO1xuICBjb25zdCBsID0gTWF0aC5tYXgoaSwgaik7XG4gIGxldCBtaWQ6IFRbXSAgPSBbXTtcbiAgbGV0IHZrOiAgVCB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDsgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmICgrK2k8ayB8fCBpPmwpIHlpZWxkIHY7XG4gICAgZWxzZSBpZiAoaT09PWspIHZrID0gdjtcbiAgICBlbHNlIGlmIChpPGwpIG1pZC5wdXNoKHYpXG4gICAgZWxzZSB7IHlpZWxkIHY7IHlpZWxkKiBtaWQ7IHlpZWxkIHZrOyBtaWQgPSBbXTsgfVxuICB9XG59XG5cblxuLyoqXG4gKiBSZW1vdmUgdmFsdWUgYXQgaW5kZXguXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGkgaW5kZXhcbiAqIEByZXR1cm5zIHhbMC4uaV0g4qe6IHhbaSsxLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogcmVtb3ZlPFQ+KHg6IEl0ZXJhYmxlPFQ+LCBpOiBudW1iZXIpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgeWllbGQqIHNwbGljZSh4LCBpLCAxKTtcbn1cblxuXG5cblxuLy8gUFJPUEVSVFlcbi8vIC0tLS0tLS0tXG5cbi8qKlxuICogQ291bnQgdmFsdWVzIHdoaWNoIHNhdGlzZnkgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgzqN04bWiIHwgdOG1oiA9IDEgaWYgZnQoduG1oikgZWxzZSAwOyB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3VudDxUPih4OiBJdGVyYWJsZTxUPiwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IG51bWJlciB7XG4gIGxldCBpID0gLTEsIGEgPSAwO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoZnQodiwgKytpLCB4KSkgKythO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIENvdW50IG9jY3VycmVuY2VzIG9mIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgTWFwIFxce3ZhbHVlIOKHkiBjb3VudFxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY291bnRBczxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IE1hcDxUfFUsIG51bWJlcj4ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBsZXQgaSA9IC0xOyBjb25zdCBhID0gbmV3IE1hcCgpO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHYxID0gZm0odiwgKytpLCB4KTtcbiAgICBhLnNldCh2MSwgKGEuZ2V0KHYxKSB8fCAwKSArIDEpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRmluZCBzbWFsbGVzdCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB2IHwgdiDiiaQgduG1ojsgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gbWluPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHJhbmdlRW50cmllcyh4LCBmYywgZm0pWzBdWzFdO1xufVxuXG5cbi8qKlxuICogRmluZCBsYXJnZXN0IHZhbHVlLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHYgfCB2IOKJpSB24bWiOyB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXg8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFQgfCB1bmRlZmluZWQge1xuICByZXR1cm4gcmFuZ2VFbnRyaWVzKHgsIGZjLCBmbSlbMV1bMV07XG59XG5cblxuLyoqXG4gKiBGaW5kIHNtYWxsZXN0IGFuZCBsYXJnZXN0IHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbbWluX3ZhbHVlLCBtYXhfdmFsdWVdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5nZTxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogW1QgfCB1bmRlZmluZWQsIFQgfCB1bmRlZmluZWRdIHtcbiAgY29uc3QgW2EsIGJdID0gcmFuZ2VFbnRyaWVzKHgsIGZjLCBmbSk7XG4gIHJldHVybiBbYVsxXSwgYlsxXV07XG59XG5cblxuLyoqXG4gKiBGaW5kIHNtYWxsZXN0IGVudHJ5LlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIFttaW5faW5kZXgsIG1pbl92YWx1ZV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pbkVudHJ5PFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBbbnVtYmVyLCBUIHwgdW5kZWZpbmVkXSB7XG4gIHJldHVybiByYW5nZUVudHJpZXMoeCwgZmMsIGZtKVswXTtcbn1cblxuXG4vKipcbiAqIEZpbmQgbGFyZ2VzdCBlbnRyeS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbbWF4X2luZGV4LCBtYXhfdmFsdWVdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXhFbnRyeTxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogW251bWJlciwgVCB8IHVuZGVmaW5lZF0ge1xuICByZXR1cm4gcmFuZ2VFbnRyaWVzKHgsIGZjLCBmbSlbMV07XG59XG5cblxuLyoqXG4gKiBGaW5kIHNtYWxsZXN0IGFuZCBsYXJnZXN0IGVudHJpZXMuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgW21pbl9lbnRyeSwgbWF4X2VudHJ5XVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZ2VFbnRyaWVzPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBbW251bWJlciwgVCB8IHVuZGVmaW5lZF0sIFtudW1iZXIsIFQgfCB1bmRlZmluZWRdXSB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgbGV0IG1pID0gLTEsIG11OiBUIHwgdW5kZWZpbmVkLCBtdjogVHxVIHwgdW5kZWZpbmVkO1xuICBsZXQgbmkgPSAtMSwgbnU6IFQgfCB1bmRlZmluZWQsIG52OiBUfFUgfCB1bmRlZmluZWQ7XG4gIGxldCBpICA9IC0xO1xuICBmb3IgKGNvbnN0IHUgb2YgeCkge1xuICAgIGNvbnN0IHYgPSBmbSh1LCArK2ksIHgpO1xuICAgIGlmIChpPT09MCB8fCBmYyh2LCBtdiBhcyBUfFUpPDApIHsgbWkgPSBpOyBtdSA9IHU7IG12ID0gdjsgfVxuICAgIGlmIChpPT09MCB8fCBmYyh2LCBudiBhcyBUfFUpPjApIHsgbmkgPSBpOyBudSA9IHU7IG52ID0gdjsgfVxuICB9XG4gIHJldHVybiBbW21pLCBtdV0sIFtuaSwgbnVdXTtcbn1cblxuXG5cblxuLy8gUEFSVFxuLy8gLS0tLVxuXG4vKipcbiAqIEdldCBwYXJ0IG9mIGFuIGl0ZXJhYmxlLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBpIHN0YXJ0IGluZGV4ICgtdmU6IGZyb20gcmlnaHQpIFswXVxuICogQHBhcmFtIEkgZW5kIGluZGV4ICgtdmU6IGZyb20gcmlnaHQpIFtFTkRdXG4gKiBAcmV0dXJucyB4W2kuLkldXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzbGljZTxUPih4OiBJdGVyYWJsZTxUPiwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj1FTkQpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgaWYgKGk+PTAgJiYgST49MCkgICAgIHJldHVybiBzbGljZVBvcyh4LCBpLCBJKTtcbiAgZWxzZSBpZiAoaT49MCAmJiBJPDApIHJldHVybiBzbGljZVBvc05lZyh4LCBpLCBJKTtcbiAgZWxzZSByZXR1cm4gc2xpY2VOZWcoeCwgaSwgSSk7XG59XG5cbmZ1bmN0aW9uKiBzbGljZVBvczxUPih4OiBJdGVyYWJsZTxUPiwgaTogbnVtYmVyLCBJOiBudW1iZXIpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgbGV0IGsgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBpZiAoKytrPj1JKSBicmVhaztcbiAgICBpZiAoaz49aSkgICB5aWVsZCB2O1xuICB9XG59XG5cbmZ1bmN0aW9uKiBzbGljZVBvc05lZzxUPih4OiBJdGVyYWJsZTxUPiwgaTogbnVtYmVyLCBJOiBudW1iZXIpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgbGV0ICAgaiA9IDAsICBrID0gLTE7XG4gIGNvbnN0IGEgPSBbXSwgQSA9IC1JO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmICgrK2s8aSkgY29udGludWU7XG4gICAgaWYgKGEubGVuZ3RoPj1BKSB5aWVsZCBhW2pdO1xuICAgIGFbal0gPSB2OyBqID0gKGorMSkgJSBBO1xuICB9XG59XG5cbmZ1bmN0aW9uKiBzbGljZU5lZzxUPih4OiBJdGVyYWJsZTxUPiwgaTogbnVtYmVyLCBJOiBudW1iZXIpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgbGV0ICAgaiA9IDAsICBYID0gMDtcbiAgY29uc3QgYSA9IFtdLCBBID0gLWk7XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgYVtqXSA9IHY7IGogPSAoaisxKSAlIEE7XG4gICAgKytYO1xuICB9XG4gIGkgPSBNYXRoLm1heChYK2ksIDApO1xuICBJID0gSTwwPyBNYXRoLm1heChYK0ksIDApIDogTWF0aC5taW4oSSwgWCk7XG4gIGNvbnN0IG4gPSBNYXRoLm1heChJLWksIDApO1xuICBjb25zdCBKID0gTWF0aC5tYXgoaituLUEsIDApO1xuICB5aWVsZCogYS5zbGljZShqLCBqK24pO1xuICB5aWVsZCogYS5zbGljZSgwLCBKKTtcbn1cblxuXG4vKipcbiAqIEdldCBmaXJzdCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gdmQgZGVmYXVsdCB2YWx1ZVxuICogQHJldHVybnMgeFswXSB8fCB2ZFxuICovXG5leHBvcnQgZnVuY3Rpb24gaGVhZDxUPih4OiBJdGVyYWJsZTxUPiwgdmQ/OiBUKTogVCB8IHVuZGVmaW5lZCB7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIHJldHVybiB2O1xuICByZXR1cm4gdmQ7XG59XG5cblxuLyoqXG4gKiBHZXQgbGFzdCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gdmQgZGVmYXVsdCB2YWx1ZVxuICogQHJldHVybnMgeFt8eHwtMV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxhc3Q8VD4oeDogSXRlcmFibGU8VD4sIHZkPzogVCk6IFQgfCB1bmRlZmluZWQge1xuICBsZXQgdiA9IHZkO1xuICBmb3IgKHYgb2YgeCk7XG4gIHJldHVybiB2O1xufVxuXG5cbi8qKlxuICogR2V0IHZhbHVlcyBleGNlcHQgZmlyc3QuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHJldHVybnMgeFsxLi58eHxdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogdGFpbDxUPih4OiBJdGVyYWJsZTxUPik6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoKytpPjApIHlpZWxkIHY7XG59XG5leHBvcnQge3RhaWwgYXMgc2hpZnR9O1xuXG5cbi8qKlxuICogR2V0IHZhbHVlcyBleGNlcHQgbGFzdC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcmV0dXJucyB4WzAuLnx4fC0xXVxuICovXG5leHBvcnQgZnVuY3Rpb24qIGluaXQ8VD4oeDogSXRlcmFibGU8VD4pOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgbGV0IHU6IFQgPSB1bmRlZmluZWQgYXMgVCwgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmICgrK2k+MCkgeWllbGQgdTtcbiAgICB1ID0gdjtcbiAgfVxufVxuZXhwb3J0IHtpbml0IGFzIHBvcH07XG5cblxuLyoqXG4gKiBHZXQgdmFsdWVzIGZyb20gbGVmdC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzXG4gKiBAcmV0dXJucyB4WzAuLm5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsZWZ0PFQ+KHg6IEl0ZXJhYmxlPFQ+LCBuOiBudW1iZXIpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgcmV0dXJuIHNsaWNlKHgsIDAsIG4pO1xufVxuXG5cbi8qKlxuICogR2V0IHZhbHVlcyBmcm9tIHJpZ2h0LlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXNcbiAqIEByZXR1cm5zIHhbLW4uLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJpZ2h0PFQ+KHg6IEl0ZXJhYmxlPFQ+LCBuOiBudW1iZXIpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgcmV0dXJuIG4hPT0wPyBzbGljZSh4LCAtbikgOiBFTVBUWTtcbn1cblxuXG4vKipcbiAqIEdldCB2YWx1ZXMgZnJvbSBtaWRkbGUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGkgc3RhcnQgaW5kZXhcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWzFdXG4gKiBAcmV0dXJucyB4W2kuLmkrbl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pZGRsZTxUPih4OiBJdGVyYWJsZTxUPiwgaTogbnVtYmVyLCBuOiBudW1iZXI9MSk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICByZXR1cm4gc2xpY2UoeCwgaSwgaStuKTtcbn1cblxuXG4vKipcbiAqIEtlZXAgZmlyc3QgbiB2YWx1ZXMgb25seS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFsxXVxuICogQHJldHVybnMgeFswLi5uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gdGFrZTxUPih4OiBJdGVyYWJsZTxUPiwgbjogbnVtYmVyPTEpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgcmV0dXJuIHNsaWNlKHgsIDAsIG4pO1xufVxuXG5cbi8qKlxuICogS2VlcCBsYXN0IG4gdmFsdWVzIG9ubHkuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbMV1cbiAqIEByZXR1cm5zIHhbLW4uLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRha2VSaWdodDxUPih4OiBJdGVyYWJsZTxUPiwgbjogbnVtYmVyPTEpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgcmV0dXJuIG4+MD8gc2xpY2UoeCwgLW4pIDogRU1QVFk7XG59XG5cblxuLyoqXG4gKiBLZWVwIHZhbHVlcyBmcm9tIGxlZnQsIHdoaWxlIGEgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4WzAuLlQtMV0gfCBmdCh4W2ldKSA9IHRydWUg4oiAIGkg4oiIIFswLCBULTFdICYgZnQoeFtUXSkgPSBmYWxzZVxuICovXG5leHBvcnQgZnVuY3Rpb24qIHRha2VXaGlsZTxUPih4OiBJdGVyYWJsZTxUPiwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmIChmdCh2LCArK2ksIHgpKSB5aWVsZCB2O1xuICAgIGVsc2UgcmV0dXJuO1xuICB9XG59XG5cblxuLyoqXG4gKiBLZWVwIHZhbHVlcyBmcm9tIHJpZ2h0LCB3aGlsZSBhIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeFtULi5dIHwgZnQoeFtpXSkgPSB0cnVlIOKIgCBpIOKIiCBbVCwgfHh8LTFdICYgZnQoeFtULTFdKSA9IGZhbHNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogdGFrZVdoaWxlUmlnaHQ8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgY29uc3QgYSA9IFtdOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmIChmdCh2LCArK2ksIHgpKSBhLnB1c2godik7XG4gICAgZWxzZSBhLmxlbmd0aCA9IDA7XG4gIH1cbiAgeWllbGQqIGE7XG59XG5cblxuLyoqXG4gKiBEaXNjYXJkIGZpcnN0IG4gdmFsdWVzIG9ubHkuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbMV1cbiAqIEByZXR1cm5zIHhbbi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZHJvcDxUPih4OiBJdGVyYWJsZTxUPiwgbjogbnVtYmVyPTEpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgcmV0dXJuIHNsaWNlKHgsIG4pO1xufVxuXG5cbi8qKlxuICogRGlzY2FyZCBsYXN0IG4gdmFsdWVzIG9ubHkuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbMV1cbiAqIEByZXR1cm5zIHhbMC4uLW5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkcm9wUmlnaHQ8VD4oeDogSXRlcmFibGU8VD4sIG46IG51bWJlcj0xKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIHJldHVybiBuPjA/IHNsaWNlKHgsIDAsIC1uKSA6IHZhbHVlcyh4KTtcbn1cblxuXG4vKipcbiAqIERpc2NhcmQgdmFsdWVzIGZyb20gbGVmdCwgd2hpbGUgYSB0ZXN0IHBhc3Nlcy5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbVC4uXSB8IGZ0KHhbaV0pID0gdHJ1ZSDiiIAgaSDiiIggWzAsIFQtMV0gJiBmdCh4W1RdKSA9IGZhbHNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogZHJvcFdoaWxlPFQ+KHg6IEl0ZXJhYmxlPFQ+LCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGxldCBjID0gdHJ1ZSwgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGMgPSBjICYmIGZ0KHYsICsraSwgeCk7XG4gICAgaWYgKCFjKSB5aWVsZCB2O1xuICB9XG59XG5cblxuLyoqXG4gKiBEaXNjYXJkIHZhbHVlcyBmcm9tIHJpZ2h0LCB3aGlsZSBhIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeFswLi5ULTFdIHwgZnQoeFtpXSkgPSB0cnVlIOKIgCBpIOKIiCBbVCwgfHh8LTFdICYgZnQoeFtULTFdKSA9IGZhbHNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogZHJvcFdoaWxlUmlnaHQ8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgY29uc3QgYSA9IFtdOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmIChmdCh2LCArK2ksIHgpKSBhLnB1c2godik7XG4gICAgZWxzZSB7IHlpZWxkKiBhOyB5aWVsZCB2OyBhLmxlbmd0aCA9IDA7IH1cbiAgfVxufVxuXG5cblxuXG4vLyBGSU5EXG4vLyAtLS0tXG5cbi8qKlxuICogQ2hlY2sgaWYgaXRlcmFibGUgaGFzIGEgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIHYgc2VhcmNoIHZhbHVlXG4gKiBAcGFyYW0gaSBzdGFydCBpbmRleCBbMF1cbiAqIEByZXR1cm5zIHYg4oiIIHhbaS4uXT9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluY2x1ZGVzPFQ+KHg6IEl0ZXJhYmxlPFQ+LCB2OiBULCBpOiBudW1iZXI9MCk6IGJvb2xlYW4ge1xuICByZXR1cm4gaGFzVmFsdWUoc2xpY2UoeCwgaSksIHYpO1xufVxuXG5cbi8qKlxuICogRmluZCBmaXJzdCBpbmRleCBvZiBhIHZhbHVlLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSB2IHNlYXJjaCB2YWx1ZVxuICogQHBhcmFtIGkgc3RhcnQgaW5kZXggWzBdXG4gKiBAcmV0dXJucyBpbmRleCBvZiB2IGluIHhbaS4uXSBpZiBmb3VuZCBlbHNlIC0xXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmRleE9mPFQ+KHg6IEl0ZXJhYmxlPFQ+LCB2OiBULCBpOiBudW1iZXI9MCk6IG51bWJlciB7XG4gIGNvbnN0IGEgPSBzZWFyY2hWYWx1ZShzbGljZSh4LCBpKSwgdik7XG4gIHJldHVybiBhPj0wPyBhK2kgOiBhO1xufVxuXG5cbi8qKlxuICogRmluZCBsYXN0IGluZGV4IG9mIGEgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIHYgc2VhcmNoIHZhbHVlXG4gKiBAcGFyYW0gaSBzdGFydCBpbmRleCBbRU5ELTFdXG4gKiBAcmV0dXJucyBsYXN0IGluZGV4IG9mIHYgaW4geFswLi5pXSBpZiBmb3VuZCBlbHNlIC0xXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsYXN0SW5kZXhPZjxUPih4OiBJdGVyYWJsZTxUPiwgdjogVCwgaTogbnVtYmVyPUVORC0xKTogbnVtYmVyIHtcbiAgcmV0dXJuIHNlYXJjaFZhbHVlUmlnaHQoc2xpY2UoeCwgMCwgaSsxKSwgdik7XG59XG5cblxuLyoqXG4gKiBGaW5kIGZpcnN0IHZhbHVlIHBhc3NpbmcgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgdiB8IGZ0KHYpID0gdHJ1ZTsgdiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZDxUPih4OiBJdGVyYWJsZTxUPiwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFQgfCB1bmRlZmluZWQge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoZnQodiwgKytpLCB4KSkgcmV0dXJuIHY7XG59XG5cblxuLyoqXG4gKiBGaW5kIGxhc3QgdmFsdWUgcGFzc2luZyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBsYXN0IHYgfCBmdCh2KSA9IHRydWU7IHYg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbmRSaWdodDxUPih4OiBJdGVyYWJsZTxUPiwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFQgfCB1bmRlZmluZWQge1xuICBsZXQgaSA9IC0xLCBhOiBUIHwgdW5kZWZpbmVkO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoZnQodiwgKytpLCB4KSkgYSA9IHY7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogU2NhbiBmcm9tIGxlZnQsIHdoaWxlIGEgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpbmRleCB3aGVyZSB0ZXN0IGZhaWxzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzY2FuV2hpbGU8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBudW1iZXIge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoIWZ0KHYsICsraSwgeCkpIHJldHVybiBpO1xuICByZXR1cm4gKytpO1xufVxuXG5cbi8qKlxuICogU2NhbiBmcm9tIHJpZ2h0LCB3aGlsZSBhIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggd2hlcmUgdGVzdCBwYXNzZXMgdGlsbCBlbmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjYW5XaGlsZVJpZ2h0PFQ+KHg6IEl0ZXJhYmxlPFQ+LCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogbnVtYmVyIHtcbiAgbGV0IGEgPSAtMSwgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoIWZ0KHYsICsraSwgeCkpIGEgPSBpO1xuICByZXR1cm4gKythO1xufVxuXG5cbi8qKlxuICogU2NhbiBmcm9tIGxlZnQsIHVudGlsIGEgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpbmRleCB3aGVyZSB0ZXN0IHBhc3Nlc1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2NhblVudGlsPFQ+KHg6IEl0ZXJhYmxlPFQ+LCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogbnVtYmVyIHtcbiAgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgaWYgKGZ0KHYsICsraSwgeCkpIHJldHVybiBpO1xuICByZXR1cm4gKytpO1xufVxuXG5cbi8qKlxuICogU2NhbiBmcm9tIHJpZ2h0LCB1bnRpbCBhIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggd2hlcmUgdGVzdCBmYWlscyB0aWxsIGVuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2NhblVudGlsUmlnaHQ8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBudW1iZXIge1xuICBsZXQgYSA9IC0xLCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmIChmdCh2LCArK2ksIHgpKSBhID0gaTtcbiAgcmV0dXJuICsrYTtcbn1cblxuXG4vKipcbiAqIEZpbmQgaW5kZXggb2YgZmlyc3QgdmFsdWUgcGFzc2luZyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpbmRleCBvZiB2YWx1ZSwgLTEgaWYgbm90IGZvdW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2g8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBudW1iZXIge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoZnQodiwgKytpLCB4KSkgcmV0dXJuIGk7XG4gIHJldHVybiAtMTtcbn1cblxuXG4vKipcbiAqIEZpbmQgaW5kZXggb2YgbGFzdCB2YWx1ZSBwYXNzaW5nIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGxhc3QgaW5kZXggb2YgdmFsdWUsIC0xIGlmIG5vdCBmb3VuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoUmlnaHQ8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBudW1iZXIge1xuICBsZXQgaSA9IC0xLCBhID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmIChmdCh2LCArK2ksIHgpKSBhID0gaTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBGaW5kIGluZGljZXMgb2YgdmFsdWVzIHBhc3NpbmcgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgaW5kaWNlcyBvZiB2YWx1ZVxuICovXG5leHBvcnQgZnVuY3Rpb24qIHNlYXJjaEFsbDxUPih4OiBJdGVyYWJsZTxUPiwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IEl0ZXJhYmxlSXRlcmF0b3I8bnVtYmVyPiB7XG4gIGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmIChmdCh2LCArK2ksIHgpKSB5aWVsZCBpO1xufVxuXG5cbi8qKlxuICogRmluZCBmaXJzdCBpbmRleCBvZiBhIHZhbHVlLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSB2IHNlYXJjaCB2YWx1ZVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggb2YgdmFsdWUsIC0xIGlmIG5vdCBmb3VuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoVmFsdWU8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgdjogVCwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlciB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgdjEgPSBmbSh2LCAwLCBudWxsKTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB1IG9mIHgpIHtcbiAgICBjb25zdCB1MSA9IGZtKHUsICsraSwgeCk7XG4gICAgaWYgKGZjKHUxLCB2MSk9PT0wKSByZXR1cm4gaTtcbiAgfVxuICByZXR1cm4gLTE7XG59XG5cblxuLyoqXG4gKiBGaW5kIGxhc3QgaW5kZXggb2YgYSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gdiBzZWFyY2ggdmFsdWVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGxhc3QgaW5kZXggb2YgdmFsdWUsIC0xIGlmIG5vdCBmb3VuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoVmFsdWVSaWdodDxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCB2OiBULCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB2MSA9IGZtKHYsIDAsIG51bGwpO1xuICBsZXQgICBpICA9IC0xLCBhID0gLTE7XG4gIGZvciAoY29uc3QgdSBvZiB4KSB7XG4gICAgY29uc3QgdTEgPSBmbSh1LCArK2ksIHgpO1xuICAgIGlmIChmYyh1MSwgdjEpPT09MCkgYSA9IGk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBGaW5kIGluZGljZXMgb2YgYSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gdiBzZWFyY2ggdmFsdWVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGluZGljZXMgb2YgdmFsdWVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBzZWFyY2hWYWx1ZUFsbDxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCB2OiBULCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogSXRlcmFibGVJdGVyYXRvcjxudW1iZXI+IHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB2MSA9IGZtKHYsIDAsIG51bGwpOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHUgb2YgeCkge1xuICAgIGNvbnN0IHUxID0gZm0odSwgKytpLCB4KTtcbiAgICBpZiAoZmModTEsIHYxKT09PTApIHlpZWxkIGk7XG4gIH1cbn1cblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgaW5kZXggb2YgYW4gaW5maXguXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIHkgc2VhcmNoIGluZml4XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpIHwgeFtpLi5pK3x5fF0gPSB5IGVsc2UgLTFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaEluZml4PFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIHk6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgcmV0dXJuIGhlYWQoc2VhcmNoSW5maXhBbGwoeCwgeSwgZmMsIGZtKSwgLTEpIGFzIG51bWJlcjtcbn1cblxuXG4vKipcbiAqIEZpbmQgbGFzdCBpbmRleCBvZiBhbiBpbmZpeC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0geSBzZWFyY2ggaW5maXhcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGZpcnN0IGkgfCB4W2kuLmkrfHl8XSA9IHkgZWxzZSAtMVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoSW5maXhSaWdodDxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCB5OiBJdGVyYWJsZTxUPiwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlciB7XG4gIHJldHVybiBsYXN0KHNlYXJjaEluZml4QWxsKHgsIHksIGZjLCBmbSksIC0xKSBhcyBudW1iZXI7XG59XG5cblxuLyoqXG4gKiBGaW5kIGluZGljZXMgb2YgYW4gaW5maXguXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIHkgc2VhcmNoIGluZml4XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBp4oKALCBp4oKBLCAuLi4gfCB4W2ouLmorfHl8XSA9IHk7IGog4oiIIFtp4oKALCBp4oKBLCAuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogc2VhcmNoSW5maXhBbGw8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgeTogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBJdGVyYWJsZUl0ZXJhdG9yPG51bWJlcj4ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHkxID0gWy4uLm1hcCh5LCBmbSldO1xuICBjb25zdCBZICA9IHkxLmxlbmd0aDtcbiAgaWYgKFk9PT0wKSB7IHlpZWxkKiBmcm9tUmFuZ2UoMCwgbGVuZ3RoKHgpKTsgcmV0dXJuOyB9XG4gIGNvbnN0IG0gID0gbmV3IEFycmF5KFkpLmZpbGwoZmFsc2UpO1xuICBsZXQgICBpICA9IC0xLCBKID0gMDtcbiAgZm9yIChjb25zdCB1IG9mIHgpIHtcbiAgICBjb25zdCB1MSA9IGZtKHUsICsraSwgeCk7XG4gICAgZm9yIChsZXQgaj1KOyBqPjA7IC0tailcbiAgICAgIG1bal0gPSBtW2otMV0gJiYgZmModTEsIHkxW2pdKT09PTA7XG4gICAgbVswXSA9IGZjKHUxLCB5MVswXSk9PT0wO1xuICAgIEogPSBNYXRoLm1pbihKKzEsIFktMSk7XG4gICAgaWYgKG1bWS0xXSkgeWllbGQgaS1ZKzE7XG4gIH1cbn1cblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgaW5kZXggb2YgYSBzdWJzZXF1ZW5jZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0geSBzZWFyY2ggc3Vic2VxdWVuY2VcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHN0YXJ0IGluZGV4IG9mIHN1YnNlcXVlbmNlLCAtMSBpZiBub3QgZm91bmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaFN1YnNlcXVlbmNlPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIHk6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB5MSA9IFsuLi5tYXAoeSwgZm0pXTtcbiAgY29uc3QgWSAgPSB5MS5sZW5ndGg7XG4gIGlmIChZPT09MCkgcmV0dXJuIDA7XG4gIGNvbnN0IHNpID0gW10sIHNuID0gW107IGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdSBvZiB4KSB7XG4gICAgY29uc3QgdTEgPSBmbSh1LCArK2ksIHgpO1xuICAgIGNvbnN0IFMgPSBzaS5sZW5ndGg7XG4gICAgZm9yIChsZXQgcz0wOyBzPFM7ICsrcykge1xuICAgICAgY29uc3QgdjEgPSB5MVtzbltzXV07XG4gICAgICBpZiAoZmModTEsIHYxKSE9PTApIGNvbnRpbnVlO1xuICAgICAgaWYgKCsrc25bc109PT1ZKSByZXR1cm4gc2lbc107XG4gICAgfVxuICAgIGNvbnN0IHYxID0geTFbMF07XG4gICAgaWYgKGZjKHUxLCB2MSkhPT0wKSBjb250aW51ZTtcbiAgICBzaS5wdXNoKGkpO1xuICAgIHNuLnB1c2goMSk7XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuXG5cbi8qKlxuICogQ2hlY2sgaWYgaXRlcmFibGUgaGFzIGEgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIHYgc2VhcmNoIHZhbHVlXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB2IOKIiCB4P1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzVmFsdWU8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgdjogVCwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICByZXR1cm4gc2VhcmNoVmFsdWUoeCwgdiwgZmMsIGZtKT49MDtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIGl0ZXJhYmxlIHN0YXJ0cyB3aXRoIGEgcHJlZml4LlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSB5IHNlYXJjaCBwcmVmaXhcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbMC4ufHl8XSA9IHk/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNQcmVmaXg8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgeTogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBpeCA9IHhbU3ltYm9sLml0ZXJhdG9yXSgpOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeSkge1xuICAgIGNvbnN0IGEgID0gaXgubmV4dCgpO1xuICAgIGlmIChhLmRvbmUpIHJldHVybiBmYWxzZTtcbiAgICBjb25zdCB1MSA9IGZtKGEudmFsdWUsICsraSwgeCk7XG4gICAgY29uc3QgdjEgPSBmbSh2LCBpLCB5KTtcbiAgICBpZiAoZmModTEsIHYxKSE9PTApIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIGl0ZXJhYmxlIGVuZHMgd2l0aCBhIHN1ZmZpeC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0geSBzZWFjaCBzdWZmaXhcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbfHh8LXx5fC4uXSA9IHk/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNTdWZmaXg8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgeTogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB5MSA9IEFycmF5LmlzQXJyYXkoeSk/IHkgOiBbLi4ueV07XG4gIGNvbnN0IFkgID0geTEubGVuZ3RoO1xuICBjb25zdCBhID0gW107IGxldCBrID0gMCwgbiA9IDA7XG4gIGlmIChZPT09MCkgcmV0dXJuIHRydWU7XG4gIGZvciAoY29uc3QgdSBvZiB4KSB7XG4gICAgYVtrKysgJSBZXSA9IHU7XG4gICAgKytuO1xuICB9XG4gIGlmIChhLmxlbmd0aDxZKSByZXR1cm4gZmFsc2U7XG4gIGZvciAobGV0IGk9MCwgaj1uLVk7IGk8WTsgKytpLCArK2opIHtcbiAgICBjb25zdCB1MSA9IGZtKGFbaysrICUgWV0sIGosIHgpO1xuICAgIGNvbnN0IHYxID0gZm0oeTFbaV0sIGksIHkpO1xuICAgIGlmIChmYyh1MSwgdjEpIT09MCkgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5cbi8qKlxuICogQ2hlY2sgaWYgaXRlcmFibGUgY29udGFpbnMgYW4gaW5maXguXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIHkgc2VhcmNoIGluZml4XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4W2kuLkldID0geSBmb3Igc29tZSBpLCBJP1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzSW5maXg8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgeTogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIHNlYXJjaEluZml4KHgsIHksIGZjLCBmbSk+PTA7XG59XG5cblxuLyoqXG4gKiBDaGVjayBpZiBpdGVyYWJsZSBoYXMgYSBzdWJzZXF1ZW5jZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0geSBzZWFyY2ggc3Vic2VxdWVuY2VcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbaeKCgF0g4qe6IHhbaeKCgV0g4qe6IC4uLiA9IHksIGZvciBzb21lIGnigoAsIGnigoEsIC4uLj8gfCBp4oKAIDwgaeKCgSA8IC4uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzU3Vic2VxdWVuY2U8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgeTogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIHNlYXJjaFN1YnNlcXVlbmNlKHgsIHksIGZjLCBmbSk+PTA7XG59XG5cblxuXG5cbi8vIEZVTkNUSU9OQUxcbi8vIC0tLS0tLS0tLS1cblxuLyoqXG4gKiBDYWxsIGEgZnVuY3Rpb24gZm9yIGVhY2ggdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGZwIHByb2Nlc3MgZnVuY3Rpb24gKHYsIGksIHgpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmb3JFYWNoPFQ+KHg6IEl0ZXJhYmxlPFQ+LCBmcDogUHJvY2Vzc0Z1bmN0aW9uPFQ+KTogdm9pZCB7XG4gIGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGZwKHYsICsraSwgeCk7XG59XG5cblxuLyoqXG4gKiBDaGVjayBpZiBhbnkgdmFsdWUgc2F0aXNmaWVzIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHRydWUgaWYgZnQoduG1oikgPSB0cnVlIGZvciBzb21lIHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNvbWU8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgaWYgKGZ0KSByZXR1cm4gc29tZVRlc3QoeCwgZnQpO1xuICBlbHNlICAgIHJldHVybiBzb21lQm9vbGVhbih4KTtcbn1cblxuZnVuY3Rpb24gc29tZUJvb2xlYW48VD4oeDogSXRlcmFibGU8VD4pOiBib29sZWFuIHtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgaWYgKHYpIHJldHVybiB0cnVlO1xuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIHNvbWVUZXN0PFQ+KHg6IEl0ZXJhYmxlPFQ+LCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogYm9vbGVhbiB7XG4gIGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmIChmdCh2LCArK2ksIHgpKSByZXR1cm4gdHJ1ZTtcbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5cbi8qKlxuICogQ2hlY2sgaWYgYWxsIHZhbHVlcyBzYXRpc2Z5IGEgdGVzdC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHRydWUgaWYgZnQoduG1oikgPSB0cnVlIGZvciBhbGwgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gZXZlcnk8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgaWYgKGZ0KSByZXR1cm4gZXZlcnlUZXN0KHgsIGZ0KTtcbiAgZWxzZSAgICByZXR1cm4gZXZlcnlCb29sZWFuKHgpO1xufVxuXG5mdW5jdGlvbiBldmVyeUJvb2xlYW48VD4oeDogSXRlcmFibGU8VD4pOiBib29sZWFuIHtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgaWYgKCF2KSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBldmVyeVRlc3Q8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBib29sZWFuIHtcbiAgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgaWYgKCFmdCh2LCArK2ksIHgpKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiB0cnVlO1xufVxuXG5cbi8qKlxuICogVHJhbnNmb3JtIHZhbHVlcyBvZiBhbiBpdGVyYWJsZS5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZm0oduKCgCksIGZtKHbigoEpLCAuLi4gfCB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogbWFwPFQsIFU+KHg6IEl0ZXJhYmxlPFQ+LCBmbTogTWFwRnVuY3Rpb248VCwgVT4pOiBJdGVyYWJsZUl0ZXJhdG9yPFU+IHtcbiAgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgeWllbGQgZm0odiwgKytpLCB4KTtcbn1cblxuXG4vKipcbiAqIFJlZHVjZSB2YWx1ZXMgb2YgaXRlcmFibGUgdG8gYSBzaW5nbGUgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGZyIHJlZHVjZSBmdW5jdGlvbiAoYWNjLCB2LCBpLCB4KVxuICogQHBhcmFtIGFjYyBpbml0aWFsIHZhbHVlXG4gKiBAcmV0dXJucyBmcihmcihhY2MsIHbigoApLCB24oKBKS4uLiB8IGZyKGFjYywgduKCgCkgPSB24oKAIGlmIGFjYyBub3QgZ2l2ZW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZHVjZTxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCBmcjogUmVkdWNlRnVuY3Rpb248VCwgVT4sIGFjYz86IFUpOiBVIHwgdW5kZWZpbmVkIHtcbiAgbGV0IGluaXQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDIsIGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBpZiAoaW5pdCkgeyBpbml0ID0gZmFsc2U7IGFjYyA9IHYgYXMgdW5rbm93biBhcyBVOyArK2k7IH1cbiAgICBlbHNlIGFjYyA9IGZyKGFjYyBhcyBVLCB2LCArK2ksIHgpO1xuICB9XG4gIHJldHVybiBhY2M7XG59XG5cblxuLyoqXG4gKiBLZWVwIHRoZSB2YWx1ZXMgd2hpY2ggcGFzcyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB24oKALCB24oKBLCAuLi4gfCBmdCh24bWiKSA9IHRydWU7IHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBmaWx0ZXI8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgaWYgKGZ0KHYsICsraSwgeCkpIHlpZWxkIHY7XG59XG5leHBvcnQge2ZpbHRlciBhcyBmaW5kQWxsfTtcblxuXG4vKipcbiAqIEtlZXAgdGhlIHZhbHVlcyBhdCBnaXZlbiBpbmRpY2VzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBpcyBpbmRpY2VzIChzb3J0ZWQpXG4gKiBAcmV0dXJucyB24oKALCB24oKBLCAuLi4gfCB24bWiID0geFtpXTsgaSDiiIggaXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBmaWx0ZXJBdDxUPih4OiBJdGVyYWJsZTxUPiwgaXM6IG51bWJlcltdKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmIChpcy5pbmNsdWRlcygrK2kpKSB5aWVsZCB2O1xufVxuXG5cbi8qKlxuICogRGlzY2FyZCB0aGUgdmFsdWVzIHdoaWNoIHBhc3MgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgduKCgCwgduKCgSwgLi4uIHwgZnQoduG1oikgPSBmYWxzZTsgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24qIHJlamVjdDxUPih4OiBJdGVyYWJsZTxUPiwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoIWZ0KHYsICsraSwgeCkpIHlpZWxkIHY7XG59XG5cblxuLyoqXG4gKiBEaXNjYXJkIHRoZSB2YWx1ZXMgYXQgZ2l2ZW4gaW5kaWNlcy5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gaXMgaW5kaWNlcyAoc29ydGVkKVxuICogQHJldHVybnMgduKCgCwgduKCgSwgLi4uIHwgduG1oiA9IHhbaV07IGkg4oiJIGlzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogcmVqZWN0QXQ8VD4oeDogSXRlcmFibGU8VD4sIGlzOiBudW1iZXJbXSk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoIWlzLmluY2x1ZGVzKCsraSkpIHlpZWxkIHY7XG59XG5cblxuLyoqXG4gKiBQcm9kdWNlIGFjY3VtdWxhdGluZyB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGZyIHJlZHVjZSBmdW5jdGlvbiAoYWNjLCB2LCBpLCB4KVxuICogQHBhcmFtIGFjYyBpbml0aWFsIHZhbHVlXG4gKiBAcmV0dXJucyBmcihhY2MsIHbigoApLCBmcihmcihhY2MsIHbigoApLCB24oKBKSwgLi4uIHwgZnIoYWNjLCB24oKAKSA9IHbigoAgaWYgYWNjIG5vdCBnaXZlblxuICovXG5leHBvcnQgZnVuY3Rpb24qIGFjY3VtdWxhdGU8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgZnI6IFJlZHVjZUZ1bmN0aW9uPFQsIFR8VT4sIGFjYz86IFR8VSk6IEl0ZXJhYmxlSXRlcmF0b3I8VHxVPiB7XG4gIGxldCBpbml0ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyLCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgaWYgKGluaXQpIHsgaW5pdCA9IGZhbHNlOyBhY2MgPSB2OyArK2k7IH1cbiAgICBlbHNlIGFjYyA9IGZyKGFjYyBhcyBULCB2LCArK2ksIHgpO1xuICAgIHlpZWxkIGFjYztcbiAgfVxufVxuXG5cbi8qKlxuICogRmxhdHRlbiBuZXN0ZWQgaXRlcmFibGUgdG8gZ2l2ZW4gZGVwdGguXG4gKiBAcGFyYW0geCBhIG5lc3RlZCBpdGVyYWJsZVxuICogQHBhcmFtIG4gbWF4aW11bSBkZXB0aCAoLTEg4oeSIGFsbClcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnQgZmxhdHRlbiB0ZXN0ICh2LCBpLCB4KSBbaXNMaXN0XVxuICogQHJldHVybnMgZmxhdCBpdGVyYWJsZVxuICovXG5leHBvcnQgZnVuY3Rpb24qIGZsYXQoeDogSXRlcmFibGU8dW5rbm93bj4sIG46IG51bWJlcj0tMSwgZm06IE1hcEZ1bmN0aW9uPHVua25vd24sIHVua25vd24+IHwgbnVsbD1udWxsLCBmdDogVGVzdEZ1bmN0aW9uPHVua25vd24+IHwgbnVsbD1udWxsKTogSXRlcmFibGVJdGVyYXRvcjx1bmtub3duPiB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGZ0ID0gKGZ0IHx8IGlzTGlzdCkgYXMgVGVzdEZ1bmN0aW9uPHVua25vd24+OyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHYxID0gZm0odiwgKytpLCB4KTtcbiAgICBpZiAobiE9PTAgJiYgZnQodjEsIGksIHgpKSB5aWVsZCogZmxhdCh2MSBhcyBJdGVyYWJsZTx1bmtub3duPiwgbi0xLCBmbSwgZnQpO1xuICAgIGVsc2UgeWllbGQgdjE7XG4gIH1cbn1cblxuXG4vKipcbiAqIEZsYXR0ZW4gbmVzdGVkIGl0ZXJhYmxlLCBiYXNlZCBvbiBtYXAgZnVuY3Rpb24uXG4gKiBAcGFyYW0geCBhIG5lc3RlZCBpdGVyYWJsZVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmdCBmbGF0dGVuIHRlc3QgKHYsIGksIHgpIFtpc0xpc3RdXG4gKiBAcmV0dXJucyBmbGF0IGl0ZXJhYmxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogZmxhdE1hcCh4OiBJdGVyYWJsZTx1bmtub3duPiwgZm06IE1hcEZ1bmN0aW9uPHVua25vd24sIHVua25vd24+IHwgbnVsbD1udWxsLCBmdDogVGVzdEZ1bmN0aW9uPHVua25vd24+IHwgbnVsbD1udWxsKTogSXRlcmFibGVJdGVyYXRvcjx1bmtub3duPiB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGZ0ID0gKGZ0IHx8IGlzTGlzdCkgYXMgVGVzdEZ1bmN0aW9uPHVua25vd24+OyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHYxID0gZm0odiwgKytpLCB4KTtcbiAgICBpZiAoZnQodjEsIGksIHgpKSB5aWVsZCogdjEgYXMgSXRlcmFibGU8dW5rbm93bj47XG4gICAgZWxzZSB5aWVsZCB2MTtcbiAgfVxufVxuXG5cbi8qKlxuICogQ29tYmluZSB2YWx1ZXMgZnJvbSBpdGVyYWJsZXMuXG4gKiBAcGFyYW0geHMgaXRlcmFibGVzXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2cywgaSwgeHMpXG4gKiBAcGFyYW0gZmUgZW5kIGZ1bmN0aW9uIChkb25lcykgW3NvbWVdXG4gKiBAcGFyYW0gdmQgZGVmYXVsdCB2YWx1ZVxuICogQHJldHVybnMgZm0oW3jigoBbMF0sIHjigoFbMF0sIC4uLl0pLCBmbShbeOKCgFsxXSwgeOKCgVsxXSwgLi4uXSksIC4uLlxuICovXG5leHBvcnQgZnVuY3Rpb24qIHppcDxULCBVPVRbXT4oeHM6IEl0ZXJhYmxlPFQ+W10sIGZtOiBNYXBGdW5jdGlvbjxUW10sIFRbXXxVPiB8IG51bGw9bnVsbCwgZmU6IEVuZEZ1bmN0aW9uIHwgbnVsbD1udWxsLCB2ZD86IFQpOiBJdGVyYWJsZUl0ZXJhdG9yPFRbXXxVPiB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGZlID0gZmUgfHwgc29tZSBhcyBFbmRGdW5jdGlvbjtcbiAgY29uc3QgWCA9IHhzLmxlbmd0aDtcbiAgaWYgKFg9PT0wKSByZXR1cm47XG4gIGNvbnN0IGl4ID0gW10sIGRzID0gW10sIHZzID0gW107XG4gIGZvciAobGV0IHI9MDsgcjxYOyByKyspXG4gICAgaXhbcl0gPSB4c1tyXVtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIGZvciAobGV0IGk9MDs7ICsraSkge1xuICAgIGZvciAobGV0IHI9MDsgcjxYOyArK3IpIHtcbiAgICAgIGNvbnN0IHtkb25lLCB2YWx1ZX0gPSBpeFtyXS5uZXh0KCk7XG4gICAgICBkc1tyXSA9IGRvbmU7XG4gICAgICB2c1tyXSA9IGRvbmU/IHZkIDogdmFsdWU7XG4gICAgfVxuICAgIGlmIChmZShkcyBhcyBib29sZWFuW10pKSBicmVhaztcbiAgICB5aWVsZCBmbSh2cy5zbGljZSgpIGFzIFRbXSwgaSwgbnVsbCk7XG4gIH1cbn1cblxuXG5cblxuLy8gTUFOSVBVTEFUSU9OXG4vLyAtLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBGaWxsIHdpdGggZ2l2ZW4gdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIHYgdmFsdWVcbiAqIEBwYXJhbSBpIHN0YXJ0IGluZGV4IFswXVxuICogQHBhcmFtIEkgZW5kIGluZGV4IFtFTkRdXG4gKiBAcmV0dXJucyB4JyB8IHgnID0geDsgeCdbaS4uSV0gPSB2XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogZmlsbDxUPih4OiBJdGVyYWJsZTxUPiwgdjogVCwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj1FTkQpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgbGV0IGogPSAtMTtcbiAgZm9yIChjb25zdCB1IG9mIHgpIHtcbiAgICBpZiAoKytqPj1pICYmIGo8SSkgeWllbGQgdjtcbiAgICBlbHNlIHlpZWxkIHU7XG4gIH1cbn1cblxuXG4vKipcbiAqIEFkZCB2YWx1ZXMgdG8gdGhlIGVuZC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gdnMgdmFsdWVzIHRvIGFkZFxuICogQHJldHVybnMgLi4ueCwgLi4udnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBwdXNoPFQ+KHg6IEl0ZXJhYmxlPFQ+LCAuLi52czogVFtdKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIHlpZWxkKiB4O1xuICB5aWVsZCogdnM7XG59XG5cblxuLyoqXG4gKiBBZGQgdmFsdWVzIHRvIHRoZSBzdGFydC5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gdnMgdmFsdWVzIHRvIGFkZFxuICogQHJldHVybnMgLi4udnMsIC4uLnhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiB1bnNoaWZ0PFQ+KHg6IEl0ZXJhYmxlPFQ+LCAuLi52czogVFtdKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIHlpZWxkKiB2cztcbiAgeWllbGQqIHg7XG59XG5cblxuLyoqXG4gKiBDb3B5IHBhcnQgb2YgaXRlcmFibGUgdG8gYW5vdGhlci5cbiAqIEBwYXJhbSB4IHRhcmdldCBpdGVyYWJsZVxuICogQHBhcmFtIHkgc291cmNlIGl0ZXJhYmxlXG4gKiBAcGFyYW0gaiB3cml0ZSBpbmRleCBbMF1cbiAqIEBwYXJhbSBpIHJlYWQgc3RhcnQgaW5kZXggWzBdXG4gKiBAcGFyYW0gSSByZWFkIGVuZCBpbmRleCBbRU5EXVxuICogQHJldHVybnMgeFswLi5qXSDip7ogeVtpLi5JXSDip7ogeFtqK0ktaS4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24qIGNvcHk8VD4oeDogSXRlcmFibGU8VD4sIHk6IEl0ZXJhYmxlPFQ+LCBqOiBudW1iZXI9MCwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj1FTkQpOiBJdGVyYWJsZUl0ZXJhdG9yPFQgfCB1bmRlZmluZWQ+IHtcbiAgbGV0IGsgPSAtMSwgSiA9IC0xO1xuICBmb3IgKGNvbnN0IHUgb2YgeCkge1xuICAgIGlmICgrK2s9PT1qKSB7XG4gICAgICBKID0gaztcbiAgICAgIGZvciAoY29uc3QgdiBvZiBzbGljZSh5LCBpLCBJKSlcbiAgICAgIHsgeWllbGQgdjsgKytKOyB9XG4gICAgfVxuICAgIGlmIChrPj1qICYmIGs8SikgY29udGludWU7XG4gICAgZWxzZSB5aWVsZCB1O1xuICB9XG4gIGlmIChrPGopIHtcbiAgICBmb3IgKDsgKytrPGo7KSB5aWVsZDtcbiAgICB5aWVsZCogc2xpY2UoeSwgaSwgSSk7XG4gIH1cbn1cblxuXG4vKipcbiAqIENvcHkgcGFydCBvZiBpdGVyYWJsZSB3aXRoaW4uXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGogd3JpdGUgaW5kZXggWzBdXG4gKiBAcGFyYW0gaSByZWFkIHN0YXJ0IGluZGV4IFswXVxuICogQHBhcmFtIEkgcmVhZCBlbmQgaW5kZXggW0VORF1cbiAqIEByZXR1cm5zIHhbMC4ual0g4qe6IHhbaS4uSV0g4qe6IHhbaitJLWkuLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBjb3B5V2l0aGluPFQ+KHg6IEl0ZXJhYmxlPFQ+LCBqOiBudW1iZXI9MCwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj1FTkQpOiBJdGVyYWJsZUl0ZXJhdG9yPFQgfCB1bmRlZmluZWQ+IHtcbiAgeCA9IHRvTWFueSh4KTsgbGV0IG4gPSBsZW5ndGgoeCk7XG4gIGZvciAoY29uc3QgdiBvZiBjb3B5KHgsIHgsIGosIGksIEkpKSB7XG4gICAgaWYgKC0tbjwwKSBicmVhaztcbiAgICB5aWVsZCB2O1xuICB9XG59XG4vLyBjb3B5V2l0aGluTGVmdCgpP1xuLy8gY29weVdpdGhpblJpZ2h0KCk/XG5cblxuLyoqXG4gKiBNb3ZlIHBhcnQgb2YgaXRlcmFibGUgd2l0aGluLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBqIHdyaXRlIGluZGV4IFswXVxuICogQHBhcmFtIGkgcmVhZCBzdGFydCBpbmRleCBbMF1cbiAqIEBwYXJhbSBJIHJlYWQgZW5kIGluZGV4IFtFTkRdXG4gKiBAcmV0dXJucyB4WzAuLmpdIOKnuiB4W2kuLkldIOKnuiB4W2ouLmldIOKnuiB4W0kuLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vdmVXaXRoaW48VD4oeDogSXRlcmFibGU8VD4sIGo6IG51bWJlcj0wLCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPUVORCk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBpZiAoajxpKSAgICAgIHJldHVybiBtb3ZlUGFydCh4LCBqLCBpLCBJKTtcbiAgZWxzZSBpZiAoaj5JKSByZXR1cm4gbW92ZVBhcnQoeCwgaSwgSSwgaik7XG4gIGVsc2UgICAgICAgICAgcmV0dXJuIHZhbHVlcyh4KTtcbn1cblxuZnVuY3Rpb24qIG1vdmVQYXJ0PFQ+KHg6IEl0ZXJhYmxlPFQ+LCBqOiBudW1iZXIsIGs6IG51bWJlciwgbDogbnVtYmVyKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGNvbnN0IHAgPSBbXTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBpZiAoKytpPGogfHwgaT49bCkgeWllbGQgdjtcbiAgICBlbHNlIHtcbiAgICAgIHAucHVzaCh2KTtcbiAgICAgIGlmIChpPGwtMSkgY29udGludWU7XG4gICAgICB5aWVsZCogcC5zbGljZShrLWopO1xuICAgICAgeWllbGQqIHAuc2xpY2UoMCwgay1qKTtcbiAgICB9XG4gIH1cbn1cblxuXG4vKipcbiAqIFJlbW92ZSBvciByZXBsYWNlcyBleGlzdGluZyB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGkgcmVtb3ZlIGluZGV4IFswXVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyB0byByZW1vdmUgW3Jlc3RdXG4gKiBAcGFyYW0gdnMgdmFsdWVzIHRvIGluc2VydFxuICogQHJldHVybnMgeFswLi5pXSDip7ogdnMg4qe6IHhbaStuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogc3BsaWNlPFQ+KHg6IEl0ZXJhYmxlPFQ+LCBpOiBudW1iZXI9MCwgbjogbnVtYmVyPUVORC1pLCAuLi52czogVFtdKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGxldCBqID0gLTE7XG4gIGZvciAoY29uc3QgdSBvZiB4KSB7XG4gICAgaWYgKCsrajxpIHx8IGo+PWkrbikgeWllbGQgdTtcbiAgICBlbHNlIGlmIChqPT09aSkgeWllbGQqIHZzO1xuICB9XG59XG5cblxuLyoqXG4gKiBCcmVhayBpdGVyYWJsZSBjb25zaWRlcmluZyB0ZXN0IGFzIHNlcGFyYXRvci5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbai4ua10g4qe6IHhbbC4ubV0g4qe6IC4uLiB8IGZ0KHhbaV0pID0gdHJ1ZTsgaSA9IDAuLmogLyBrLi5sIC8gLi4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogc3BsaXQ8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBJdGVyYWJsZUl0ZXJhdG9yPFRbXT4ge1xuICBsZXQgYTogVFtdID0gW10sIGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBpZiAoIWZ0KHYsICsraSwgeCkpIGEucHVzaCh2KTtcbiAgICBlbHNlIGlmIChhLmxlbmd0aD4wKSB7IHlpZWxkIGE7IGEgPSBbXTsgfVxuICB9XG4gIGlmIChhLmxlbmd0aD4wKSB5aWVsZCBhO1xufVxuXG5cbi8qKlxuICogQnJlYWsgaXRlcmFibGUgY29uc2lkZXJpbmcgaW5kaWNlcyBhcyBzZXBhcmF0b3IuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGlzIGluZGljZXMgKHNvcnRlZClcbiAqIEByZXR1cm5zIHhbai4ua10g4qe6IHhbbC4ubV0g4qe6IC4uLiB8IGZ0KHhbaV0pID0gdHJ1ZTsgaSA9IDAuLmogLyBrLi5sIC8gLi4uOyBpIOKIiCBpc1xuICovXG5leHBvcnQgZnVuY3Rpb24qIHNwbGl0QXQ8VD4oeDogSXRlcmFibGU8VD4sIGlzOiBudW1iZXJbXSk6IEl0ZXJhYmxlSXRlcmF0b3I8VFtdPiB7XG4gIGxldCBhOiBUW10gPSBbXSwgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmICghaXMuaW5jbHVkZXMoKytpKSkgYS5wdXNoKHYpO1xuICAgIGVsc2UgaWYgKGEubGVuZ3RoPjApIHsgeWllbGQgYTsgYSA9IFtdOyB9XG4gIH1cbiAgaWYgKGEubGVuZ3RoPjApIHlpZWxkIGE7XG59XG5cblxuLyoqXG4gKiBCcmVhayBpdGVyYWJsZSB3aGVuIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeFswLi5qXSDip7ogeFtqLi5rXSDip7ogLi4uIHwgZnQoeFtpXSkgPSB0cnVlOyBpID0gaiwgaywgLi4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogY3V0PFQ+KHg6IEl0ZXJhYmxlPFQ+LCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogSXRlcmFibGVJdGVyYXRvcjxUW10+IHtcbiAgbGV0IGkgPSAtMSwgYSA9IFtdO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmIChmdCh2LCArK2ksIHgpKSB7IHlpZWxkIGE7IGEgPSBbXTsgfVxuICAgIGEucHVzaCh2KTtcbiAgfVxuICB5aWVsZCBhO1xufVxuXG5cbi8qKlxuICogQnJlYWsgaXRlcmFibGUgYWZ0ZXIgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4WzAuLmorMV0g4qe6IHhbaisxLi5rXSDip7ogLi4uIHwgZnQoeFtpXSkgPSB0cnVlOyBpID0gaiwgaywgLi4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogY3V0UmlnaHQ8VD4oeDogSXRlcmFibGU8VD4sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBJdGVyYWJsZUl0ZXJhdG9yPFRbXT4ge1xuICBsZXQgaSA9IC0xLCBhID0gW107XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgYS5wdXNoKHYpO1xuICAgIGlmIChmdCh2LCArK2ksIHgpKSB7IHlpZWxkIGE7IGEgPSBbXTsgfVxuICB9XG4gIHlpZWxkIGE7XG59XG5cblxuLyoqXG4gKiBCcmVhayBpdGVyYWJsZSBhdCBnaXZlbiBpbmRpY2VzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBpcyBzcGxpdCBpbmRpY2VzIChzb3J0ZWQpXG4gKiBAcmV0dXJucyB4WzAuLmpdIOKnuiB4W2ouLmtdIOKnuiAuLi4gfCBmdCh4W2ldKSA9IHRydWU7IGkgPSBqLCBrLCAuLi47IGkg4oiIIGlzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogY3V0QXQ8VD4oeDogSXRlcmFibGU8VD4sIGlzOiBJdGVyYWJsZTxudW1iZXI+KTogSXRlcmFibGVJdGVyYXRvcjxUW10+IHtcbiAgY29uc3QgaWkgPSBpc1tTeW1ib2wuaXRlcmF0b3JdKCk7XG4gIGxldCBpICA9IGlpLm5leHQoKTtcbiAgaWYgKGkuZG9uZSkgaS52YWx1ZSA9IEVORDtcbiAgbGV0IGE6IFRbXSA9IFtdLCBqID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgaWYgKCsrajxpLnZhbHVlKSB7IGEucHVzaCh2KTsgY29udGludWU7IH1cbiAgICB5aWVsZCBhOyBhID0gW3ZdO1xuICAgIGkgPSBpaS5uZXh0KCk7XG4gICAgaWYgKGkuZG9uZSkgaS52YWx1ZSA9IEVORDtcbiAgfVxuICB5aWVsZCBhO1xuICBmb3IgKDsgIWkuZG9uZTsgaT1paS5uZXh0KCkpIHlpZWxkIFtdO1xufVxuXG5cbi8qKlxuICogQnJlYWsgaXRlcmFibGUgYWZ0ZXIgZ2l2ZW4gaW5kaWNlcy5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gaXMgc3BsaXQgaW5kaWNlcyAoc29ydGVkKVxuICogQHJldHVybnMgeFswLi5qKzFdIOKnuiB4W2orMS4ua10g4qe6IC4uLiB8IGZ0KHhbaV0pID0gdHJ1ZTsgaSA9IGosIGssIC4uLjsgaSDiiIggaXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBjdXRBdFJpZ2h0PFQ+KHg6IEl0ZXJhYmxlPFQ+LCBpczogSXRlcmFibGU8bnVtYmVyPik6IEl0ZXJhYmxlSXRlcmF0b3I8VFtdPiB7XG4gIHlpZWxkKiBjdXRBdCh4LCBtYXAoaXMsIGkgPT4gaSsxKSk7XG59XG5cblxuLyoqXG4gKiBLZWVwIHNpbWlsYXIgdmFsdWVzIHRvZ2V0aGVyIGFuZCBpbiBvcmRlci5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4WzAuLmtdLCB4W2suLmxdLCAuLi4gfCBmYyh4W2ldLCB4W2pdKSA9IDA7IGksIGogPSAwLi5rIC8gay4ubCAvIC4uLlxuICovXG5leHBvcnQgZnVuY3Rpb24qIGdyb3VwPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBJdGVyYWJsZUl0ZXJhdG9yPFRbXT4ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGxldCBhOiBUW10gPSBbXSwgdTE6IFR8VSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCwgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHYxID0gZm0odiwgKytpLCB4KTtcbiAgICBpZiAoaT4wICYmIGZjKHUxIGFzIFR8VSwgdjEpIT09MCkgeyB5aWVsZCBhOyBhID0gW3ZdOyB9XG4gICAgZWxzZSBhLnB1c2godik7XG4gICAgdTEgPSB2MTtcbiAgfVxuICB5aWVsZCBhO1xufVxuXG5cbi8qKlxuICogU2VncmVnYXRlIHZhbHVlcyBieSB0ZXN0IHJlc3VsdC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIFtzYXRpc2ZpZXMsIGRvZXNudF1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnRpdGlvbjxUPih4OiBJdGVyYWJsZTxUPiwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFtUW10sIFRbXV0ge1xuICBjb25zdCB0OiBUW10gPSBbXSwgZjogVFtdID0gW107IGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgaWYgKGZ0KHYsICsraSwgeCkpIHQucHVzaCh2KTtcbiAgICBlbHNlIGYucHVzaCh2KTtcbiAgfVxuICByZXR1cm4gW3QsIGZdO1xufVxuXG5cbi8qKlxuICogU2VncmVnYXRlIHZhbHVlcyBieSBzaW1pbGFyaXR5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBNYXAgXFx7a2V5IOKHkiB2YWx1ZXNcXH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnRpdGlvbkFzPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogTWFwPFR8VSwgVFtdPiB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IGEgID0gbmV3IE1hcCgpOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHYxID0gZm0odiwgKytpLCB4KTtcbiAgICBpZiAoIWEuaGFzKHYxKSkgYS5zZXQodjEsIFtdKTtcbiAgICBhLmdldCh2MSkucHVzaCh2KTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEJyZWFrIGl0ZXJhYmxlIGludG8gY2h1bmtzIG9mIGdpdmVuIHNpemUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIG4gY2h1bmsgc2l6ZSBbMV1cbiAqIEBwYXJhbSBzIGNodW5rIHN0ZXAgW25dXG4gKiBAcmV0dXJucyB4WzAuLm5dLCB4W3MuLnMrbl0sIHhbMnMuLjJzK25dLCAuLi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBjaHVuazxUPih4OiBJdGVyYWJsZTxUPiwgbjogbnVtYmVyPTEsIHM6IG51bWJlcj1uKTogSXRlcmFibGVJdGVyYXRvcjxUW10+IHtcbiAgY29uc3QgTSA9IE1hdGgubWF4KG4sIHMpO1xuICBsZXQgbSA9IDAsIGE6IFRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmIChtPG4pIGEucHVzaCh2KTtcbiAgICBpZiAoKyttPE0pIGNvbnRpbnVlO1xuICAgIGRvIHsgeWllbGQgYTsgfSB3aGlsZSAoczw9MCk7XG4gICAgYSA9IGEuc2xpY2Uocyk7XG4gICAgbSA9IGEubGVuZ3RoO1xuICB9XG4gIGlmIChhLmxlbmd0aD4wKSB5aWVsZCBhO1xufVxuXG5cbi8qKlxuICogT2J0YWluIHZhbHVlcyB0aGF0IGN5Y2xlIHRocm91Z2ggYW4gaXRlcmFibGUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGkgc3RhcnQgaW5kZXggWzBdXG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgSW5mXVxuICogQHJldHVybnMgeFtpLi5dIOKnuiB4IOKnuiB4IOKnuiAuLi4gd2l0aCB1cHRvIG4gdmFsdWVzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogY3ljbGU8VD4oeDogSXRlcmFibGU8VD4sIGk6IG51bWJlcj0wLCBuOiBudW1iZXI9LTEpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgeCA9IHRvTWFueSh4KTsgbGV0IFggPSAwO1xuICBpZiAoaTwwKSB7XG4gICAgWCA9IGxlbmd0aCh4KTtcbiAgICBpZiAoWD09PTApIHJldHVybjtcbiAgICBpID0gbW9kKGksIFgpO1xuICB9XG4gIHdoaWxlICh0cnVlKSB7XG4gICAgWCA9IDA7XG4gICAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICAgICsrWDtcbiAgICAgIGlmICgtLWk+PTApICBjb250aW51ZTtcbiAgICAgIGlmIChuLS09PT0wKSByZXR1cm47XG4gICAgICB5aWVsZCB2O1xuICAgIH1cbiAgICBpZiAoWD09PTApIHJldHVybjtcbiAgICBpZiAoaT49WCkgIGkgPSBtb2QoaSwgWCk7XG4gIH1cbn1cblxuXG4vKipcbiAqIFJlcGVhdCBhbiBpdGVyYWJsZSBnaXZlbiB0aW1lcy5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gbiB0aW1lcyBbLTEg4oeSIEluZl1cbiAqIEByZXR1cm5zIC4uLngsIC4uLngsIC4uLihuIHRpbWVzKVxuICovXG5leHBvcnQgZnVuY3Rpb24qIHJlcGVhdDxUPih4OiBJdGVyYWJsZTxUPiwgbjogbnVtYmVyPS0xKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIHggPSB0b01hbnkoeCk7XG4gIGZvciAoOyBuIT09MDsgLS1uKVxuICAgIHlpZWxkKiB4O1xufVxuXG5cbi8qKlxuICogUmV2ZXJzZSB0aGUgdmFsdWVzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEByZXR1cm5zIHhbfHh8LTFdLCB4W3x4fC0yXSwgLi4uLCB4WzFdLCB4WzBdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogcmV2ZXJzZTxUPih4OiBJdGVyYWJsZTxUPik6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBjb25zdCBhID0gQXJyYXkuaXNBcnJheSh4KT8geCA6IFsuLi54XTtcbiAgZm9yIChsZXQgaT1hLmxlbmd0aC0xOyBpPj0wOyAtLWkpXG4gICAgeWllbGQgYVtpXTtcbn1cblxuXG4vKipcbiAqIFJvdGF0ZSB2YWx1ZXMgaW4gaXRlcmFibGUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIG4gcm90YXRlIGFtb3VudCAoK3ZlOiBsZWZ0LCAtdmU6IHJpZ2h0KSBbMF1cbiAqIEByZXR1cm5zIHhbbi4uXSDip7ogeFswLi5uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gcm90YXRlPFQ+KHg6IEl0ZXJhYmxlPFQ+LCBuOiBudW1iZXI9MCk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBpZiAobj09PTApICAgIHJldHVybiB2YWx1ZXMoeCk7XG4gIGVsc2UgaWYgKG4+MCkgcmV0dXJuIHJvdGF0ZUxlZnQgKHgsICBuKTtcbiAgZWxzZSAgICAgICAgICByZXR1cm4gcm90YXRlUmlnaHQoeCwgLW4pO1xufVxuXG5mdW5jdGlvbiogcm90YXRlTGVmdDxUPih4OiBJdGVyYWJsZTxUPiwgbjogbnVtYmVyKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGNvbnN0IGEgPSBbXTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBpZiAoKytpPG4pIGEucHVzaCh2KTtcbiAgICBlbHNlIHlpZWxkIHY7XG4gIH1cbiAgaWYgKCsraT09PTAgfHwgaT49bikgeyB5aWVsZCogYTsgcmV0dXJuOyB9XG4gIG4gPSBuICUgaTtcbiAgeWllbGQqIGEuc2xpY2Uobik7XG4gIHlpZWxkKiBhLnNsaWNlKDAsIG4pO1xufVxuXG5mdW5jdGlvbiogcm90YXRlUmlnaHQ8VD4oeDogSXRlcmFibGU8VD4sIG46IG51bWJlcik6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBjb25zdCBhID0gQXJyYXkuZnJvbSh4KTtcbiAgaWYgKGEubGVuZ3RoPT09MCkgcmV0dXJuO1xuICBuID0gbiAlIGEubGVuZ3RoO1xuICB5aWVsZCogYS5zbGljZSgtbik7XG4gIHlpZWxkKiBhLnNsaWNlKDAsIC1uKTtcbn1cblxuXG4vKipcbiAqIFBsYWNlIGEgc2VwYXJhdG9yIGJldHdlZW4gZXZlcnkgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIHYgc2VwYXJhdG9yXG4gKiBAcmV0dXJucyB4WzBdLCB2LCB4WzFdLCB2LCAuLi4sIHhbfHh8LTFdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogaW50ZXJzcGVyc2U8VD4oeDogSXRlcmFibGU8VD4sIHY6IFQpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB1IG9mIHgpIHtcbiAgICBpZiAoKytpPjApIHlpZWxkIHY7XG4gICAgeWllbGQgdTtcbiAgfVxufVxuXG5cbi8qKlxuICogRXN0aW1hdGUgbmV3IHZhbHVlcyBiZXR3ZWVuIGV4aXN0aW5nIG9uZXMuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHBhcmFtIGZjIGNvbWJpbmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcmV0dXJucyB4WzBdLCBmYyh4WzBdLCB4WzFdKSwgeFsxXSwgZmMoeFsxXSwgeFsyXSksIC4uLiwgeFt8eHwtMV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBpbnRlcnBvbGF0ZTxUPih4OiBJdGVyYWJsZTxUPiwgZmM6IENvbWJpbmVGdW5jdGlvbjxUPik6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBsZXQgdTogVCB8IHVuZGVmaW5lZCwgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmICgrK2k+MCkgeWllbGQgZmModSBhcyBULCB2KTtcbiAgICB5aWVsZCAodSA9IHYpO1xuICB9XG59XG5cblxuLyoqXG4gKiBQbGFjZSB2YWx1ZXMgb2YgYW4gaXRlcmFibGUgYmV0d2VlbiBhbm90aGVyLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSB5IGFub3RoZXIgaXRlcmFibGVcbiAqIEBwYXJhbSBtIG51bWJlciBvZiB2YWx1ZXMgZnJvbSB4IFsxXVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBmcm9tIHkgWzFdXG4gKiBAcGFyYW0gcyBzdGVwIHNpemUgZm9yIHggW21dXG4gKiBAcGFyYW0gdCBzdGVwIHNpemUgZm9yIHkgW25dXG4gKiBAcmV0dXJucyB4WzAuLm1dLCB5WzAuLm5dLCB4W3MuLnMrbV0sIHlbdC4udCtuXSwgLi4uLCB4W2sqcy4ufHh8LTFdIHwgayDiiIggV1xuICovXG5leHBvcnQgZnVuY3Rpb24qIGludGVybWl4PFQ+KHg6IEl0ZXJhYmxlPFQ+LCB5OiBJdGVyYWJsZTxUPiwgbTogbnVtYmVyPTEsIG46IG51bWJlcj0xLCBzOiBudW1iZXI9bSwgdDogbnVtYmVyPW4pOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgY29uc3QgeDEgPSBjaHVuayh4LCBtLCBzKTtcbiAgY29uc3QgeTEgPSBjaHVuayhyZXBlYXQoeSksIG4sIHQpO1xuICBjb25zdCBpeSA9IHkxW1N5bWJvbC5pdGVyYXRvcl0oKTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB1IG9mIHgxKSB7XG4gICAgaWYgKCsraT4wKSB5aWVsZCogaXkubmV4dCgpLnZhbHVlO1xuICAgIHlpZWxkKiB1O1xuICB9XG59XG5cblxuLyoqXG4gKiBQbGFjZSB2YWx1ZXMgZnJvbSBpdGVyYWJsZXMgYWx0ZXJuYXRlbHkuXG4gKiBAcGFyYW0geHMgaXRlcmFibGVzXG4gKiBAcmV0dXJucyB44oKAWzBdLCB44oKBWzBdLCAuLi4sIHjigoBbMV0sIHjigoFbMF0sIC4uLiB8IFt44oKALCB44oKBLCAuLi5dID0geHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBpbnRlcmxlYXZlPFQ+KHhzOiBJdGVyYWJsZTxUPltdKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGNvbnN0IFggID0geHMubGVuZ3RoO1xuICBpZiAoWD09PTApIHJldHVybjtcbiAgY29uc3QgaXg6IChJdGVyYXRvcjxUPiB8IG51bGwpW10gPSBbXTtcbiAgZm9yIChsZXQgaT0wOyBpPFg7ICsraSlcbiAgICBpeFtpXSA9IHhzW2ldW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgZm9yIChsZXQgaT0wLCBuPVg7IG4+MDsgaT0oaSsxKSVYKSB7XG4gICAgaWYgKGl4W2ldPT1udWxsKSBjb250aW51ZTtcbiAgICBjb25zdCBhID0gKGl4W2ldIGFzIEl0ZXJhdG9yPFQ+KS5uZXh0KCk7XG4gICAgaWYgKGEuZG9uZSkgeyBpeFtpXSA9IG51bGw7IC0tbjsgfVxuICAgIGVsc2UgeWllbGQgYS52YWx1ZSBhcyBUO1xuICB9XG59XG5cblxuXG5cbi8vIENPTUJJTkVcbi8vIC0tLS0tLS1cblxuLyoqXG4gKiBBcHBlbmQgdmFsdWVzIGZyb20gaXRlcmFibGVzLlxuICogQHBhcmFtIHhzIGl0ZXJhYmxlc1xuICogQHJldHVybnMgLi4ueOKCgCwgLi4ueOKCgSwgLi4uIHwgW3jigoAsIHjigoEsIC4uLl0gPSB4c1xuICovXG5leHBvcnQgZnVuY3Rpb24qIGNvbmNhdDxUPiguLi54czogSXRlcmFibGU8VD5bXSk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBmb3IgKGNvbnN0IHggb2YgeHMpXG4gICAgeWllbGQqIHg7XG59XG5cblxuLyoqXG4gKiBNZXJnZSB2YWx1ZXMgZnJvbSBzb3J0ZWQgaXRlcmFibGVzLlxuICogQHBhcmFtIHhzIGl0ZXJhYmxlc1xuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgc29ydChjb25jYXQoLi4ueHMpKVxuICovXG5leHBvcnQgZnVuY3Rpb24qIG1lcmdlPFQsIFU9VD4oeHM6IEl0ZXJhYmxlPFQ+W10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgY29uc3QgWCAgPSB4cy5sZW5ndGg7XG4gIGNvbnN0IGl4OiBJdGVyYXRvcjxUPltdID0gW10sIGF4OiBJdGVyYXRvclJlc3VsdDxUPltdID0gW107XG4gIGxldCBpID0gMDtcbiAgZm9yIChsZXQgbj0wOyBuPFg7ICsrbikge1xuICAgIGl4W2ldID0geHNbaV1bU3ltYm9sLml0ZXJhdG9yXSgpO1xuICAgIGF4W2ldID0gaXhbaV0ubmV4dCgpO1xuICAgIGlmICghYXhbaV0uZG9uZSkgKytpO1xuICB9XG4gIHdoaWxlIChpPjApIHtcbiAgICBjb25zdCBhcyA9IGF4Lm1hcChhID0+IGEudmFsdWUpO1xuICAgIGNvbnN0IGogID0gbWluRW50cnkoYXMsIGZjLCBmbSlbMF07XG4gICAgeWllbGQgYXNbal07XG4gICAgYXhbal0gPSBpeFtqXS5uZXh0KCk7XG4gICAgaWYgKCFheFtqXS5kb25lKSBjb250aW51ZTtcbiAgICBpeC5zcGxpY2UoaiwgMSk7XG4gICAgYXguc3BsaWNlKGosIDEpO1xuICAgIC0taTtcbiAgfVxufVxuXG5cbi8qKlxuICogSm9pbiB2YWx1ZXMgdG9nZXRoZXIgaW50byBhIHN0cmluZy5cbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlXG4gKiBAcGFyYW0gc2VwIHNlcGFyYXRvciBbLF1cbiAqIEByZXR1cm5zIFwiJFxce3bigoBcXH0kXFx7c2VwXFx9JFxce3bigoFcXH0uLi5cIiB8IHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGpvaW48VD4oeDogSXRlcmFibGU8VD4sIHNlcDogc3RyaW5nPVwiLFwiKTogc3RyaW5nIHtcbiAgbGV0IGEgPSBcIlwiO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBhICs9IHYgKyBzZXA7XG4gIHJldHVybiBhLnN1YnN0cmluZygwLCBhLmxlbmd0aC1zZXAubGVuZ3RoKTtcbn1cblxuXG5cblxuLy8gU0VUIE9QRVJBVElPTlNcbi8vIC0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlcmUgYXJlIG5vIGR1cGxpY2F0ZSB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMg4oiAIHbhtaIsIHbisbwg4oiIIHgsIGlzIHbhtaIg4omgIHbisbw/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1VuaXF1ZTxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGlmIChmYykgcmV0dXJuIGlzVW5pcXVlRHVhbCh4LCBmYywgZm0pO1xuICBlbHNlICAgIHJldHVybiBpc1VuaXF1ZU1hcCAoeCwgZm0pO1xufVxuXG5mdW5jdGlvbiBpc1VuaXF1ZU1hcDxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB4MSA9IG5ldyBTZXQoKTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBjb25zdCB2MSA9IGZtKHYsICsraSwgeCk7XG4gICAgaWYgKHgxLmhhcyh2MSkpIHJldHVybiBmYWxzZTtcbiAgICB4MS5hZGQodjEpO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBpc1VuaXF1ZUR1YWw8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHgxID0gWy4uLm1hcCh4LCBmbSldO1xuICBmb3IgKGNvbnN0IHUxIG9mIHgxKSB7XG4gICAgZm9yIChjb25zdCB2MSBvZiB4MSlcbiAgICAgIGlmIChmYyh1MSwgdjEpPT09MCkgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5cbi8qKlxuICogQ2hlY2tzIGlmIGFycmF5cyBoYXZlIG5vIHZhbHVlIGluIGNvbW1vbi5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBhbm90aGVyIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4IOKIqSB5ID0gzqY/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Rpc2pvaW50PFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIHk6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGlmIChmYykgcmV0dXJuIGlzRGlzam9pbnREdWFsKHgsIHksIGZjLCBmbSk7XG4gIGVsc2UgICAgcmV0dXJuIGlzRGlzam9pbnRNYXAgKHgsIHksIGZtKTtcbn1cblxuZnVuY3Rpb24gaXNEaXNqb2ludE1hcDxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCB5OiBJdGVyYWJsZTxUPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgY29uc3QgeTEgPSB0b1NldCh5LCBmbSk7IGxldCBpID0gLTE7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGZvciAoY29uc3QgdSBvZiB4KSB7XG4gICAgY29uc3QgdTEgPSBmbSh1LCArK2ksIHgpO1xuICAgIGlmICh5MS5oYXModTEpKSByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGlzRGlzam9pbnREdWFsPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIHk6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgeTEgPSBbLi4ubWFwKHksIGZtKV07IGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdSBvZiB4KSB7XG4gICAgY29uc3QgdTEgPSBmbSh1LCArK2ksIHgpO1xuICAgIGZvciAoY29uc3QgdjEgb2YgeTEpXG4gICAgICBpZiAoZmModTEsIHYxKT09PTApIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuXG4vKipcbiAqIFJlbW92ZSBkdXBsaWNhdGUgdmFsdWVzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHbigoAsIHbigoEsIC4uLiB8IHbhtaIg4oiIIHg7IHbhtaIg4omgIHbisbwg4oiAIGksIGpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiB1bmlxdWU8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBpZiAoZmMpIHlpZWxkKiB1bmlxdWVEdWFsKHgsIGZjLCBmbSk7XG4gIGVsc2UgICAgeWllbGQqIHVuaXF1ZU1hcCAoeCwgZm0pO1xufVxuXG5mdW5jdGlvbiogdW5pcXVlTWFwPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHgxID0gbmV3IFNldCgpOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHYxID0gZm0odiwgKytpLCB4KTtcbiAgICBpZiAoeDEuaGFzKHYxKSkgY29udGludWU7XG4gICAgeDEuYWRkKHYxKTsgeWllbGQgdjtcbiAgfVxufVxuXG5mdW5jdGlvbiogdW5pcXVlRHVhbDxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgeDEgPSBbXTsgbGV0IGkgPSAtMTtcbiAgTkVYVFg6IGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgY29uc3QgdjEgPSBmbSh2LCArK2ksIHgpO1xuICAgIGZvciAoY29uc3QgdTEgb2YgeDEpXG4gICAgICBpZiAoZmModTEsIHYxKT09PTApIGNvbnRpbnVlIE5FWFRYO1xuICAgIHgxLnB1c2godjEpOyB5aWVsZCB2O1xuICB9XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gdmFsdWVzIHByZXNlbnQgaW4gYW55IGl0ZXJhYmxlLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSB5IGFub3RoZXIgaXRlcmFibGVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHgg4oiqIHkgPSBcXHt2IHwgdiDiiIggeCBvciB2IOKIiCB5XFx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogdW5pb248VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgeTogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgaWYgKGZjKSB5aWVsZCogdW5pb25EdWFsKHgsIHksIGZjLCBmbSk7XG4gIGVsc2UgICAgeWllbGQqIHVuaW9uTWFwICh4LCB5LCBmbSk7XG59XG5cbmZ1bmN0aW9uKiB1bmlvbk1hcDxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCB5OiBJdGVyYWJsZTxUPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgeDEgPSBuZXcgU2V0KCk7XG4gIGxldCBpICA9IC0xLCBqID0gLTE7XG4gIGZvciAoY29uc3QgdSBvZiB4KSB7XG4gICAgY29uc3QgdTEgPSBmbSh1LCArK2ksIHgpO1xuICAgIHgxLmFkZCh1MSk7IHlpZWxkIHU7XG4gIH1cbiAgZm9yIChjb25zdCB2IG9mIHkpIHtcbiAgICBjb25zdCB2MSA9IGZtKHYsICsraiwgeSk7XG4gICAgaWYgKCF4MS5oYXModjEpKSB5aWVsZCB2O1xuICB9XG59XG5cbmZ1bmN0aW9uKiB1bmlvbkR1YWw8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgeTogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICB4ICA9IHRvTWFueSh4KTsgeWllbGQqIHg7XG4gIGNvbnN0IHgxID0gWy4uLm1hcCh4LCBmbSldOyBsZXQgaiA9IC0xO1xuICBORVhUWTogZm9yIChjb25zdCB2IG9mIHkpIHtcbiAgICBjb25zdCB2MSA9IGZtKHYsICsraiwgeSk7XG4gICAgZm9yIChjb25zdCB1MSBvZiB4MSlcbiAgICAgIGlmIChmYyh1MSwgdjEpPT09MCkgY29udGludWUgTkVYVFk7XG4gICAgeWllbGQgdjtcbiAgfVxufVxuXG5cbi8qKlxuICogT2J0YWluIHZhbHVlcyBwcmVzZW50IGluIGJvdGggaXRlcmFibGVzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSB5IGFub3RoZXIgaXRlcmFibGVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHgg4oipIHkgPSBcXHt2IHwgdiDiiIggeCwgdiDiiIggeVxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24qIGludGVyc2VjdGlvbjxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCB5OiBJdGVyYWJsZTxUPiwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBpZiAoZmMpIHlpZWxkKiBpbnRlcnNlY3Rpb25EdWFsKHgsIHksIGZjLCBmbSk7XG4gIGVsc2UgICAgeWllbGQqIGludGVyc2VjdGlvbk1hcCAoeCwgeSwgZm0pO1xufVxuXG5mdW5jdGlvbiogaW50ZXJzZWN0aW9uTWFwPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIHk6IEl0ZXJhYmxlPFQ+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICBjb25zdCB5MSA9IHRvU2V0KHksIGZtKTsgbGV0IGkgPSAtMTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgZm9yIChjb25zdCB1IG9mIHgpIHtcbiAgICBjb25zdCB1MSA9IGZtKHUsICsraSwgeCk7XG4gICAgaWYgKHkxLmhhcyh1MSkpIHlpZWxkIHU7XG4gIH1cbn1cblxuZnVuY3Rpb24qIGludGVyc2VjdGlvbkR1YWw8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgeTogSXRlcmFibGU8VD4sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB5MSA9IFsuLi5tYXAoeSwgZm0pXTsgbGV0IGkgPSAtMTtcbiAgTkVYVFg6IGZvciAoY29uc3QgdSBvZiB4KSB7XG4gICAgY29uc3QgdTEgPSBmbSh1LCArK2ksIHgpO1xuICAgIGZvciAoY29uc3QgdjEgb2YgeTEpXG4gICAgICBpZiAoZmModTEsIHYxKT09PTApIHsgeWllbGQgdTsgY29udGludWUgTkVYVFg7IH1cbiAgfVxufVxuXG5cbi8qKlxuICogT2J0YWluIHZhbHVlcyBub3QgcHJlc2VudCBpbiBhbm90aGVyIGl0ZXJhYmxlLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSB5IGFub3RoZXIgaXRlcmFibGVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHggLSB5ID0gXFx7diB8IHYg4oiIIHgsIHYg4oiJIHlcXH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBkaWZmZXJlbmNlPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIHk6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGlmIChmYykgeWllbGQqIGRpZmZlcmVuY2VEdWFsKHgsIHksIGZjLCBmbSk7XG4gIGVsc2UgICAgeWllbGQqIGRpZmZlcmVuY2VNYXAgKHgsIHksIGZtKTtcbn1cblxuZnVuY3Rpb24qIGRpZmZlcmVuY2VNYXA8VCwgVT1UPih4OiBJdGVyYWJsZTxUPiwgeTogSXRlcmFibGU8VD4sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGNvbnN0IHkxID0gdG9TZXQoeSwgZm0pOyBsZXQgaSA9IC0xO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBmb3IgKGNvbnN0IHUgb2YgeCkge1xuICAgIGNvbnN0IHUxID0gZm0odSwgKytpLCB4KTtcbiAgICBpZiAoIXkxLmhhcyh1MSkpIHlpZWxkIHU7XG4gIH1cbn1cblxuZnVuY3Rpb24qIGRpZmZlcmVuY2VEdWFsPFQsIFU9VD4oeDogSXRlcmFibGU8VD4sIHk6IEl0ZXJhYmxlPFQ+LCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogSXRlcmFibGVJdGVyYXRvcjxUPiB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgeTEgPSBbLi4ubWFwKHksIGZtKV07IGxldCBpID0gLTE7XG4gIE5FWFRYOiBmb3IgKGNvbnN0IHUgb2YgeCkge1xuICAgIGNvbnN0IHUxID0gZm0odSwgKytpLCB4KTtcbiAgICBmb3IgKGNvbnN0IHYxIG9mIHkxKVxuICAgICAgaWYgKGZjKHUxLCB2MSk9PT0wKSBjb250aW51ZSBORVhUWDtcbiAgICB5aWVsZCB1O1xuICB9XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gdmFsdWVzIG5vdCBwcmVzZW50IGluIGJvdGggaXRlcmFibGVzLlxuICogQHBhcmFtIHggYW4gaXRlcmFibGVcbiAqIEBwYXJhbSB5IGFub3RoZXIgaXRlcmFibGVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHgteSDiiKogeS14XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogc3ltbWV0cmljRGlmZmVyZW5jZTxULCBVPVQ+KHg6IEl0ZXJhYmxlPFQ+LCB5OiBJdGVyYWJsZTxUPiwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IEl0ZXJhYmxlSXRlcmF0b3I8VD4ge1xuICB4ID0gdG9NYW55KHgpOyB5ID0gdG9NYW55KHkpO1xuICB5aWVsZCogZGlmZmVyZW5jZSh4LCB5LCBmYywgZm0pO1xuICB5aWVsZCogZGlmZmVyZW5jZSh5LCB4LCBmYywgZm0pO1xufVxuXG5cblxuXG4vKipcbiAqIExpc3QgY2FydGVzaWFuIHByb2R1Y3Qgb2YgaXRlcmFibGVzLlxuICogQHBhcmFtIHhzIGl0ZXJhYmxlc1xuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodnMsIGkpXG4gKiBAcmV0dXJucyB44oKAIMOXIHjigoEgw5cgLi4uID0gXFx7W3bigoAsIHbigoEsIC4uLl0gfCB24oKAIOKIiCB44oKALCB24oKBIOKIiCB44oKBLCAuLi5dIFxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24qIGNhcnRlc2lhblByb2R1Y3Q8VCwgVT1UPih4czogSXRlcmFibGU8VD5bXSwgZm06IE1hcEZ1bmN0aW9uPFRbXSwgVFtdfFU+IHwgbnVsbD1udWxsKTogSXRlcmFibGVJdGVyYXRvcjxUW118VT4ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBYICA9IHhzLmxlbmd0aDtcbiAgaWYgKFg9PT0wKSByZXR1cm47XG4gIGNvbnN0IGp4ID0gW10sIGl4ID0gW10sIGF4ID0gW107XG4gIGZvciAobGV0IGk9MDsgaTxYOyArK2kpIHtcbiAgICBqeFtpXSA9IGk+MD8gdG9NYW55KHhzW2ldKSA6IHhzW2ldO1xuICAgIGl4W2ldID0ganhbaV1bU3ltYm9sLml0ZXJhdG9yXSgpO1xuICAgIGF4W2ldID0gaXhbaV0ubmV4dCgpO1xuICAgIGlmIChheFtpXS5kb25lKSByZXR1cm47XG4gIH1cbiAgZm9yIChsZXQgaT0wOzsgKytpKSB7XG4gICAgY29uc3QgdnMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IGEgb2YgYXgpIHZzLnB1c2goYS52YWx1ZSk7XG4gICAgeWllbGQgZm0odnMsIGksIG51bGwpO1xuICAgIGxldCByID0gWC0xO1xuICAgIGZvciAoOyByPj0wOyAtLXIpIHtcbiAgICAgIGF4W3JdID0gaXhbcl0ubmV4dCgpO1xuICAgICAgaWYgKCFheFtyXS5kb25lKSBicmVhaztcbiAgICAgIGl4W3JdID0ganhbcl1bU3ltYm9sLml0ZXJhdG9yXSgpO1xuICAgICAgYXhbcl0gPSBpeFtyXS5uZXh0KCk7XG4gICAgfVxuICAgIGlmIChyPDApIGJyZWFrO1xuICB9XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsU0FBUSxRQUFRLEVBQUUsT0FBTyxRQUFP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