extra-array
Version:
An [array] is a collection of values, stored contiguously.<br>
2,954 lines • 281 kB
JavaScript
// #region TYPES
// =============
/** Entries is an array of index-value pairs, with unique indices. */ // #endregion
// #region METHODS
// ===============
// #region HELPERS
// ---------------
/** Return the same (first) value. */ function IDENTITY(v) {
return v;
}
/** Compare two values. */ function COMPARE(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
}
/** Find the remainder of x/y with sign of y (floored division). */ function mod(x, y) {
return x - y * Math.floor(x / y);
}
/** 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;
}
// #endregion
// #region GENERATE
// ----------------
/**
* Generate array from given number range.
* @param v start number
* @param V end number, excluding
* @param dv step size [1]
* @returns [v, v+dv, v+2dv, ...]
*/ export function fromRange(v, V, dv = 1) {
const n = (V - v) / dv, a = [];
for(let i = 0; i < n; ++i, v += dv)a.push(v);
return a;
}
/**
* Generate array from repeated function invocation.
* @param fn function
* @param n number of values
* @returns [fn(), fn(), ...]
*/ export function fromInvocation(fn, n) {
const a = [];
for(let i = 0; i < n; ++i)a.push(fn());
return a;
}
export { fromInvocation as fromCall };
/**
* Generate array from repeated function application.
* @param fm map function (v, i)
* @param v start value
* @param n number of values
* @returns [v, fm(v), fm(fm(v)), ...]
*/ export function fromApplication(fm, v, n) {
const a = [];
if (n !== 0) a.push(v);
for(let i = 1; i !== n; ++i)a.push(v = fm(v, i, null));
return a;
}
export { fromApplication as fromApply };
/**
* Convert an iterable to array.
* @param x an iterable
* @returns x as array
*/ export function fromIterable(x) {
return [
...x
];
}
export { fromIterable as from };
/**
* Convert an iterable to array!
* @param x an iterable (updatable if array!)
* @returns x as array
*/ export function fromIterable$(x) {
return Array.isArray(x) ? x : [
...x
];
}
export { fromIterable$ as from$ };
// #endregion
// #region CLONE
// -------------
/**
* Shallow clone an array.
* @param x an array
* @returns shallow clone of x
*/ export function shallowClone(x) {
return x.slice();
}
export { shallowClone as clone };
/**
* Deep clone an array.
* @param x an array
* @returns deep clone of x
*/ export function deepClone(x) {
return structuredClone(x);
}
// #endregion
// #region ABOUT
// -------------
/**
* Check if value is an array.
* @param v a value
* @returns v is an array?
*/ export function is(v) {
return Array.isArray(v);
}
/**
* Obtain all indices.
* @param x an array
* @returns [0, 1, ..., |x|-1]
*/ export function keys(x) {
return [
...x.keys()
];
}
/**
* List all indices.
* @param x an array
* @returns 0, 1, ..., |x|-1
*/ export function ikeys(x) {
return x.keys();
}
/**
* Get all values.
* @param x an array
* @returns [v₀, v₁, ...] | vᵢ = x[i]
*/ export function values(x) {
return x.slice();
}
/**
* List all values.
* @param x an array
* @returns v₀, v₁, ... | vᵢ = x[i]
*/ export function ivalues(x) {
return x.values();
}
/**
* Obtain all index-value pairs.
* @param x an array
* @returns [[0, v₀], [1, v₁], ...] | vᵢ = x[i]
*/ export function entries(x) {
return [
...x.entries()
];
}
/**
* List all index-value pairs.
* @param x an array
* @returns [0, v₀], [1, v₁], ... | vᵢ = x[i]
*/ export function ientries(x) {
return x.entries();
}
// #endregion
// #region INDEX
// -------------
/**
* Get zero-based index for an element in array.
* @param x an array
* @param i ±index
* @returns i' | x[i'] = x[i]; i' ∈ [0, |x|]
*/ export function index(x, i) {
const X = x.length;
return i >= 0 ? Math.min(i, X) : Math.max(X + i, 0);
}
/**
* Get zero-based index range for part of array.
* @param x an array
* @param i begin ±index [0]
* @param I end ±index (exclusive) [|x|]
* @returns [i', I'] | i' ≤ I'; i', I' ∈ [0, |x|]
*/ export function indexRange(x, i = 0, I = x.length) {
const X = x.length;
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)
];
}
// #endregion
// #region LENGTH
// --------------
/**
* Check if an array is empty.
* @param x an array
* @returns |x| = 0?
*/ export function isEmpty(x) {
return x.length === 0;
}
/**
* Find the length of an array.
* @param x an array
* @param i begin ±index [0]
* @param I end ±index (exclusive) [X]
* @returns |x[i..I]|
*/ export function length(x, i = 0, I = x.length) {
[i, I] = indexRange(x, i, I);
return I - i;
}
export { length as size };
/**
* Resize an array to given length!
* @param x an array
* @param n new length
* @param vd default value
* @returns resized x
*/ export function resize$(x, n, vd) {
const X = x.length;
x.length = n;
if (n > X) x.fill(vd, X);
return x;
}
/**
* Remove all elements from an array!
* @param x an array (updated!)
* @returns cleared x
*/ export function clear$(x) {
x.length = 0;
return x;
}
// #endregion
// #region GET/SET
// ---------------
/**
* Get value at index.
* @param x an array
* @param i index
* @returns x[i]
*/ export function get(x, i) {
return x[index(x, i)];
}
export { get as at };
// Get values at index range.
// export {slice as getRange};
/**
* Get values at indices.
* @param x an array
* @param is indices
* @returns [x[i₀], x[i₁], ...] | [i₀, i₁, ...] = is
*/ export function getAll(x, is) {
return is.map((i)=>get(x, i));
}
/**
* Get value at path in a nested array.
* @param x a nested array
* @param p path
* @returns x[i₀][i₁][...] | [i₀, i₁, ...] = p
*/ export function getPath(x, p) {
let a = x;
for (const i of p)a = is(a) ? get(a, i) : undefined;
return a;
}
/**
* Check if nested array has a path.
* @param x a nested array
* @param p path
* @returns x[i₀][i₁][...] exists? | [i₀, i₁, ...] = p
*/ export function hasPath(x, p) {
let a = x;
for (const i of p){
if (!is(a)) return false;
a = get(a, i);
}
return true;
}
/**
* Set value at index.
* @param x an array
* @param i index
* @param v value
* @returns x' | x' = x; x'[i] = v
*/ export function set(x, i, v) {
return set$(x.slice(), i, v);
}
export { set as with };
/**
* Set value at index!
* @param x an array (updated!)
* @param i index
* @param v value
* @returns x | x[i] = v
*/ export function set$(x, i, v) {
x[index(x, i)] = v;
return x;
}
// TODO: setRange$()
// TODO: setAll$()
/**
* Set value at path in a nested array!
* @param x a nested array (updated!)
* @param p path
* @param v value
* @returns x | x[i₀][i₁][...] = v; [i₀, i₁, ...] = p
*/ export function setPath$(x, p, v) {
const y = getPath(x, p.slice(0, -1));
if (is(y)) set$(y, last(p), v);
return x;
}
/**
* Exchange two values.
* @param x an array
* @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) {
return swap$(x.slice(), i, j);
}
/**
* Exchange two values!
* @param x an array (updated!)
* @param i an index
* @param j another index
* @returns x | x[i] ⇔ x[j]
*/ export function swap$(x, i, j) {
i = index(x, i);
j = index(x, j);
const t = x[i];
x[i] = x[j];
x[j] = t;
return x;
}
/**
* Exchange two values!
* @param x an array (updated!)
* @param i an +ve index
* @param j another +ve index
* @returns x | x[i] ⇔ x[j]
*/ function swapRaw$(x, i, j) {
const t = x[i];
x[i] = x[j];
x[j] = t;
return x;
}
// NOTE: May also be called swapUnchecked$().
/**
* Exchange two ranges of values.
* @param x an array
* @param i begin index of first range
* @param I end index of first range (exclusive)
* @param j begin index of second range
* @param J end index of second range (exclusive)
* @returns x' | x' = x; x'[i..I] = x[j..J]; x'[j..J] = x[i..I]
*/ export function swapRanges(x, i, I, j, J) {
[i, I] = indexRange(x, i, I);
[j, J] = indexRange(x, j, J);
if (j < i) [i, I, j, J] = [
j,
J,
i,
I
];
if (j < I) return x.slice(); // Skip if ranges overlap!
return x.slice(0, i).concat(x.slice(j, J), x.slice(i, j), x.slice(I));
}
/**
* Exchange two ranges of values!
* @param x an array (updated!)
* @param i begin index of first range
* @param I end index of first range (exclusive)
* @param j begin index of second range
* @param J end index of second range (exclusive)
* @returns x | x[i..I] ⇔ x[j..J]
*/ export function swapRanges$(x, i, I, j, J) {
[i, I] = indexRange(x, i, I);
[j, J] = indexRange(x, j, J);
if (j < i) [i, I, j, J] = [
j,
J,
i,
I
];
if (j < I) return x; // Skip if ranges overlap!
const t = x.slice(i, I);
x.splice(i, I - i, ...x.slice(j, J));
x.splice(j, J - j, ...t);
return x;
}
// TODO: swapAll$()
/**
* Remove value at index.
* @param x an array
* @param i index
* @returns x[0..i] ⧺ x[i+1..]
*/ export function remove(x, i) {
i = index(x, i);
return x.slice(0, i).concat(x.slice(i + 1));
}
/**
* Remove value at index!
* @param x an array (updated!)
* @param i index
* @returns x \\: [i]
*/ export function remove$(x, i) {
x.splice(i, 1);
return x;
}
/**
* Remove value at path in a nested array!
* @param x a nested array (updated!)
* @param p path
* @returns x \\: [i₀][i₁][...] | [i₀, i₁, ...] = p
*/ export function removePath$(x, p) {
const y = getPath(x, p.slice(0, -1));
if (is(y)) y.splice(last(p), 1);
return x;
}
// #endregion
// #region SORT
// ------------
/**
* Examine if array is sorted.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x is sorted?
*/ export function isSorted(x, fc = null, fm = null) {
return searchUnsortedValue(x, fc, fm) === -1;
}
/**
* Examine if array has an unsorted value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x is not sorted?
*/ export function hasUnsortedValue(x, fc = null, fm = null) {
return searchUnsortedValue(x, fc, fm) >= 0;
}
/**
* Find first index of an unsorted value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns index of first unsorted value, -1 if sorted
*/ export function searchUnsortedValue(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
if (X <= 1) return -1;
let w0 = fm(x[0], 0, x);
for(let i = 1; i < X; ++i){
const w = fm(x[i], i, x);
if (fc(w0, w) > 0) return i;
w0 = w;
}
return -1;
}
/**
* Arrange values in order.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x' | x' = x; x'[i] ≤ x'[j] ∀ i ≤ j
*/ export function sort(x, fc = null, fm = null, fs = null) {
return sort$(x.slice(), fc, fm, fs);
}
export { sort as toSorted };
/**
* Arrange values in order!
* @param x an array (updated!)
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ export function sort$(x, fc = null, fm = null, fs = null) {
fc = fc || COMPARE;
if (!fm && !fs) return x.sort(fc);
const X = x.length;
fm = fm || IDENTITY;
fs = fs || swapRaw$;
return rangedPartialIntroSort$(x, 0, X, X, fc, fm, fs);
}
/**
* Arrange a range of values in order.
* @param x an array
* @param i begin index
* @param I end index (exclusive)
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x' | x' = x; x'[i] ≤ x'[j] ∀ i ≤ j
*/ export function rangedSort(x, i, I, fc = null, fm = null, fs = null) {
return rangedSort$(x.slice(), i, I, fc, fm, fs);
}
/**
* Arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ export function rangedSort$(x, i, I, fc = null, fm = null, fs = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
fs = fs || swapRaw$;
[i, I] = indexRange(x, i, I);
return rangedPartialIntroSort$(x, i, I, I - i, fc, fm, fs);
}
/**
* Partially arrange values in order.
* @param x an array
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x' | x' = x; x'[i] ≤ x'[j] ∀ i ≤ j
*/ export function partialSort(x, n, fc = null, fm = null, fs = null) {
return partialSort$(x.slice(), n, fc, fm, fs);
}
/**
* Partially arrange values in order!
* @param x an array (updated!)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ export function partialSort$(x, n, fc = null, fm = null, fs = null) {
return rangedPartialSort$(x, 0, x.length, n, fc, fm, fs);
}
/**
* Partially arrange a range of values in order.
* @param x an array
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x' | x' = x; x'[i] ≤ x'[j] ∀ i ≤ j
*/ export function rangedPartialSort(x, i, I, n, fc = null, fm = null, fs = null) {
return rangedPartialSort$(x.slice(), i, I, n, fc, fm, fs);
}
/**
* Partially arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ export function rangedPartialSort$(x, i, I, n, fc = null, fm = null, fs = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
fs = fs || swapRaw$;
[i, I] = indexRange(x, i, I);
return rangedPartialIntroSort$(x, i, I, n, fc, fm, fs);
}
/**
* Partially arrange values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ function rangedPartialIntroSort$(x, i, I, n, fc, fm, fs) {
const d = Math.floor(Math.log2(I - i) * 2); // Maximum depth of recursion
const s = 16; // When to switch to insertion sort
return rangedPartialIntroSortDo$(x, i, I, d, s, n, fc, fm, fs);
}
// Partially arrange a range of values in order with hybrid quick sort, heap sort, and insertion sort.
function rangedPartialIntroSortDo$(x, i, I, d, s, n, fc, fm, fs) {
if (n <= 0 || I - i <= 1) return x; // Nothing to sort
if (I - i <= s) return rangedPartialInsertionSort$(x, i, I, n, fc, fm, fs); // Insertion sort
if (d <= 0) return rangedPartialHeapSort$(x, i, I, n, fc, fm, fs); // Heap sort
let p = i + Math.floor((I - i) * Math.random()); // Choose pivot
p = rangedQuickSortPartition$(x, i, I, p, fc, fm, fs); // Partition array
rangedPartialIntroSortDo$(x, i, p, d, s, Math.min(p - i, n), fc, fm, fs); // Sort left part
rangedPartialIntroSortDo$(x, p + 1, I, d, s, Math.min(I - p - 1, n), fc, fm, fs); // Sort right part
return x;
}
/**
* Partially arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ function _rangedPartialQuickSort$(x, i, I, n, fc, fm, fs) {
if (n <= 0 || I - i <= 1) return x; // Nothing to sort
let p = i + Math.floor((I - i) * Math.random()); // Choose pivot
p = rangedQuickSortPartition$(x, i, I, p, fc, fm, fs); // Partition array
_rangedPartialQuickSort$(x, i, p, Math.min(p - i, n), fc, fm, fs); // Sort left part
_rangedPartialQuickSort$(x, p + 1, I, Math.min(I - p - 1, n), fc, fm, fs); // Sort right part
return x;
}
// TODO: Make this a generic function.
// Partition the array into two parts, such that values in the first part are less than values in the second part.
function rangedQuickSortPartition$(x, i, I, p, fc, fm, fs) {
const wp = fm(x[p], p, x); // Pivot value
let j = i - 1; // Last index of values ≤ pivot
fs(x, p, I - 1); // Move pivot to end
for(let k = i; k < I - 1; ++k){
const wk = fm(x[k], k, x);
if (fc(wk, wp) > 0) continue;
fs(x, ++j, k); // Move value ≤ pivot to left
}
fs(x, ++j, I - 1); // Move pivot to middle
return j; // Return pivot index
}
/**
* Partially arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ function rangedPartialHeapSort$(x, i, I, n, fc, fm, fs) {
rangedBuildReverseMinHeap$(x, i, I, fc, fm, fs);
for(const r = I - 1; n > 0 && i < I; ++i, --n){
fs(x, i, r); // Move root to the beginning
rangedReverseMinHeapify$(x, i + 1, I, r, fc, fm, fs); // Rebuild heap
}
return x;
}
// Build a reverse min-heap from a range of values, where root node is the smallest and placed at the end.
function rangedBuildReverseMinHeap$(x, i, I, fc, fm, fs) {
for(let r = I - Math.floor((I - i) / 2); r < I; ++r)rangedReverseMinHeapify$(x, i, I, r, fc, fm, fs);
}
/**
* Reverse min-heapify a range of values, such that root node is the smallest and placed at the end.
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param r root index
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
*/ function rangedReverseMinHeapify$(x, i, I, r, fc, fm, fs) {
let s = r; // Index of smallest value
const lt = 2 * r - I; // Left child, reverse of lt = 2*r+1
const rt = lt - 1; // Right child, reverse of rt = 2*r+2
if (lt >= i && fc(fm(x[lt], lt, x), fm(x[s], s, x)) < 0) s = lt; // Left child is smaller?
if (rt >= i && fc(fm(x[rt], rt, x), fm(x[s], s, x)) < 0) s = rt; // Right child is smaller?
if (s !== r) {
fs(x, s, r); // Swap root with smallest
rangedReverseMinHeapify$(x, i, I, s, fc, fm, fs); // Rebuild heap
}
}
// Build a max-heap from a range of values, where root node is the smallest and placed at the beginning.
function rangedBuildMaxHeap$(x, i, I, fc, fm, fs) {
for(let r = i + Math.floor((I - i) / 2) - 1; r >= i; --r)rangedMaxHeapify$(x, i, I, r, fc, fm, fs);
}
/**
* Max-heapify a range of values, such that root node is the largest and placed at the beginning.
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param r root index
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
*/ function rangedMaxHeapify$(x, i, I, r, fc, fm, fs) {
let s = r; // Index of largest value
const lt = 2 * r - i + 1; // Left child, like lt = 2*r+1
const rt = lt + 1; // Right child, like rt = 2*r+2
if (lt < I && fc(fm(x[lt], lt, x), fm(x[s], s, x)) > 0) s = lt; // Left child is larger?
if (rt < I && fc(fm(x[rt], rt, x), fm(x[s], s, x)) > 0) s = rt; // Right child is larger?
if (s !== r) {
fs(x, s, r); // Swap root with largest
rangedMaxHeapify$(x, i, I, s, fc, fm, fs); // Rebuild heap
}
}
/**
* Partially arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort (ignored)
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ function rangedPartialInsertionSort$(x, i, I, n, fc, fm, fs) {
// NOTE: Insertion sort does not support partial sorting, so we ignore n.
if (fs === swapRaw$) return rangedPartialInsertionSortSwapless$(x, i, I, n, fc, fm, fs);
else return rangedPartialInsertionSortSwap$(x, i, I, n, fc, fm, fs);
}
// Sort a range of values in order with swap-enabled version of insertion sort.
function rangedPartialInsertionSortSwap$(x, i, I, _n, fc, fm, fs) {
for(let j = i + 1; j < I; ++j){
const key = x[j];
const wkey = fm(key, j, x);
for(let k = j - 1; k >= i && fc(fm(x[k], k, x), wkey) > 0; --k)fs(x, k, k + 1);
}
return x;
}
// Sort a range of values in order with swapless version of insertion sort.
function rangedPartialInsertionSortSwapless$(x, i, I, _n, fc, fm, _fs) {
for(let j = i + 1; j < I; ++j){
const key = x[j];
const wkey = fm(key, j, x);
let k = j - 1;
for(; k >= i && fc(fm(x[k], k, x), wkey) > 0; --k)x[k + 1] = x[k];
x[k + 1] = key;
}
return x;
}
/**
* Partially arrange a range of values in order!
* @param x an array (updated!)
* @param i begin index
* @param I end index (exclusive)
* @param n minimum number of values to sort
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @param fs swap function (x, i, j)
* @returns x | x[i] ≤ x[j] ∀ i ≤ j
*/ function _rangedPartialSelectionSort$(x, i, I, n, fc, fm, fs) {
for(let j = i; n > 0 && j < I; ++j, --n){
let l = j;
let wl = fm(x[l], l, x);
for(let k = j + 1; k < I; ++k){
const wk = fm(x[k], k, x);
if (fc(wl, wk) > 0) {
l = k;
wl = wk;
}
}
fs(x, j, l);
}
return x;
}
// #endregion
// #region MINIMUM/MAXIMUM
// -----------------------
/**
* Find first smallest value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns v | v ≤ vᵢ; vᵢ ∈ x
*/ export function minimum(x, fc = null, fm = null) {
const i = searchMinimumValue(x, fc, fm);
return x[i];
}
export { minimum as min };
/**
* Find first smallest entry.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns [min_index, min_value]
*/ export function minimumEntry(x, fc = null, fm = null) {
const i = searchMinimumValue(x, fc, fm);
return [
i,
x[i]
];
}
export { minimumEntry as minEntry };
/**
* Find first largest value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns v | v ≥ vᵢ; vᵢ ∈ x
*/ export function maximum(x, fc = null, fm = null) {
const i = searchMaximumValue(x, fc, fm);
return x[i];
}
export { maximum as max };
/**
* Find first largest entry.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns [max_index, max_value]
*/ export function maximumEntry(x, fc = null, fm = null) {
const i = searchMaximumValue(x, fc, fm);
return [
i,
x[i]
];
}
export { maximumEntry as maxEntry };
/**
* Find smallest and largest values.
* @param x an array
* @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 and largest entries.
* @param x an array
* @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;
const X = x.length;
if (X === 0) return [
[
-1,
undefined
],
[
-1,
undefined
]
];
let v = x[0], w = fm(v, 0, x);
let mi = 0, mv = v, mw = w;
let ni = 0, nv = v, nw = w;
for(let i = 1; i < X; ++i){
v = x[i];
w = fm(v, i, x);
if (fc(w, mw) < 0) {
mi = i;
mv = v;
mw = w;
}
if (fc(w, nw) > 0) {
ni = i;
nv = v;
nw = w;
}
}
return [
[
mi,
mv
],
[
ni,
nv
]
];
}
/**
* Find smallest values.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns n smallest values in ascending order
*/ export function minimums(x, n, fc = null, fm = null) {
const is = searchMinimumValues(x, n, fc, fm);
return is.map((i)=>x[i]);
}
/**
* Find smallest entries.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns n smallest entries in ascending order
*/ export function minimumEntries(x, n, fc = null, fm = null) {
const is = searchMinimumValues(x, n, fc, fm);
return is.map((i)=>[
i,
x[i]
]);
}
/**
* Find largest values.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns n largest values in descending order
*/ export function maximums(x, n, fc = null, fm = null) {
const is = searchMaximumValues(x, n, fc, fm);
return is.map((i)=>x[i]);
}
/**
* Find largest entries.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns n largest entries in descending order
*/ export function maximumEntries(x, n, fc = null, fm = null) {
const is = searchMaximumValues(x, n, fc, fm);
return is.map((i)=>[
i,
x[i]
]);
}
/**
* Find first index of minimum value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first index of minimum value, -1 if empty
*/ export function searchMinimumValue(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
if (X === 0) return -1;
let mi = 0, mw = fm(x[0], 0, x);
for(let i = 1; i < X; ++i){
const w = fm(x[i], i, x);
if (fc(w, mw) < 0) {
mi = i;
mw = w;
}
}
return mi;
}
/**
* Find first index of maximum value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first index of maximum value, -1 if empty
*/ export function searchMaximumValue(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
if (X === 0) return -1;
let ni = 0, nw = fm(x[0], 0, x);
for(let i = 1; i < X; ++i){
const w = fm(x[i], i, x);
if (fc(w, nw) > 0) {
ni = i;
nw = w;
}
}
return ni;
}
/**
* Find indices of minimum values.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns indices of minimum values in ascending order
*/ export function searchMinimumValues(x, n, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
// Create a max heap of indices.
const IH = Math.min(n, X);
const ih = fromRange(0, IH);
rangedBuildMaxHeap$(ih, 0, IH, fc, (i)=>fm(x[i], i, x), swapRaw$);
let wr = fm(x[ih[0]], ih[0], x);
// Search for minimum values, and update heap.
for(let i = n; i < X; ++i){
const w = fm(x[i], i, x);
if (fc(w, wr) >= 0) continue;
ih[0] = i;
rangedMaxHeapify$(ih, 0, IH, 0, fc, (i)=>fm(x[i], i, x), swapRaw$);
wr = fm(x[ih[0]], ih[0], x);
}
// Sort max heap in ascending order.
ih.sort((i, j)=>fc(fm(x[i], i, x), fm(x[j], j, x)));
return ih;
}
/**
* Find indices of maximum values.
* @param x an array
* @param n number of values
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns indices of maximum values in descending order
*/ export function searchMaximumValues(x, n, fc = null, fm = null) {
fc = fc || COMPARE;
const fd = (a, b)=>-fc(a, b);
return searchMinimumValues(x, n, fd, fm);
}
// #endregion
// #region COMPARE
// ---------------
/**
* Examine if two arrays are equal.
* @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 isEqual(x, y, fc = null, fm = null) {
const X = x.length, Y = y.length;
return X === Y && compare(x, y, fc, fm) === 0;
}
/**
* Compare two arrays (lexicographically).
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x<y: -ve, x=y: 0, x>y: +ve
*/ export function compare(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
const Y = y.length;
for(let i = 0, I = Math.min(X, Y); i < I; ++i){
const wx = fm(x[i], i, x);
const wy = fm(y[i], i, y);
const c = fc(wx, wy);
if (c !== 0) return c;
}
return Math.sign(X - Y);
}
// #endregion
// #region PART
// ------------
/**
* Get first value.
* @param x an array
* @param vd default value
* @returns x[0] || vd
*/ export function head(x, vd) {
return x.length > 0 ? x[0] : vd;
}
export { head as front };
export { head as first };
/**
* Get values except first.
* @param x an array
* @returns x[1..|x|]
*/ export function tail(x) {
return x.slice(1);
}
/**
* Get values except last.
* @param x an array
* @returns x[0..|x|-1]
*/ export function init(x) {
return x.slice(0, -1);
}
/**
* Get last value.
* @param x an array
* @param vd default value
* @returns x[|x|-1] || vd
*/ export function last(x, vd) {
return x.length > 0 ? x[x.length - 1] : vd;
}
export { last as back };
/**
* Get values from middle.
* @param x an array
* @param i begin index
* @param n number of values [1]
* @returns x[i..i+n]
*/ export function middle(x, i, n = 1) {
i = index(x, i);
n = Math.max(n, 0);
return x.slice(i, i + n);
}
/**
* Get part of an array.
* @param x an array
* @param i begin index [0]
* @param I end index [|x|]
* @returns x[i..I]
*/ export function slice(x, i = 0, I = x.length) {
return x.slice(i, I);
}
/**
* Get part of an array!
* @param x an array (updated!)
* @param i begin index [0]
* @param I end index [|x|]
* @returns x = x[i..I]
*/ export function slice$(x, i = 0, I = x.length) {
x.copyWithin(0, i, I);
x.length = length(x, i, I);
return x;
}
// #endregion
// #region SEARCH VALUE
// --------------------
/**
* Check if array has a value.
* @param x an array
* @param v search value
* @param i begin index [0]
* @returns v ∈ x[i..]?
*/ export function includes(x, v, i = 0) {
return x.includes(v, i);
}
/**
* Examine if array has a value.
* @param x an array
* @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;
}
/**
* Find first index of a value.
* @param x an array
* @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 w = fm(v, 0, null);
let i = -1;
for (const vx of x){
const wx = fm(vx, ++i, x);
if (fc(wx, w) === 0) return i;
}
return -1;
}
/**
* Find last index of a value.
* @param x an array
* @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 w = fm(v, 0, null);
for(let i = x.length - 1; i >= 0; --i){
const wx = fm(x[i], i, x);
if (fc(wx, w) === 0) return i;
}
return -1;
}
/**
* Find indices of value.
* @param x an array
* @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 w = fm(v, 0, null);
let i = -1;
const a = [];
for (const vx of x){
const wx = fm(vx, ++i, x);
if (fc(wx, w) === 0) a.push(i);
}
return a;
}
/**
* Find first index of an adjacent duplicate value.
* @param x an array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns index of first adjacent duplicate value, -1 if none
*/ export function searchAdjacentDuplicateValue(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
if (X <= 1) return -1;
let w0 = fm(x[0], 0, x);
for(let i = 1; i < X; ++i){
const w = fm(x[i], i, x);
if (fc(w0, w) === 0) return i;
w0 = w;
}
return -1;
}
export { searchAdjacentDuplicateValue as searchAdjacentDuplicate };
/**
* Find first index where two arrays differ.
* @param x an array
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns first index where x[i] ≠ y[i], or -1
*/ export function searchMismatchedValue(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length;
const Y = y.length;
const I = Math.min(X, Y);
for(let i = 0; i < I; ++i){
const wx = fm(x[i], i, x);
const wy = fm(y[i], i, y);
if (fc(wx, wy) !== 0) return i;
}
return X === Y ? -1 : I;
}
export { searchMismatchedValue as searchMismatch };
// #endregion
// #region ARRANGEMENTS
// --------------------
/**
* Examine if array starts with a prefix.
* @param x an array
* @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) {
const Y = y.length;
return Y === 0 || compare(x.slice(0, Y), y, fc, fm) === 0;
}
export { hasPrefix as startsWith };
/**
* Examine if array ends with a suffix.
* @param x an array
* @param y search 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) {
const Y = y.length;
return Y === 0 || compare(x.slice(-Y), y, fc, fm) === 0;
}
export { hasSuffix as endsWith };
/**
* Examine if array contains an infix.
* @param x an array
* @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;
}
/**
* Examine if array has a subsequence.
* @param x an array
* @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;
}
/**
* Examine if array has a permutation.
* @param x an array
* @param y search permutation
* @param fc map function (v, i, x)
* @param fm compare function (a, b)
* @returns x contains a shuffled version of y?
*/ export function hasPermutation(x, y, fc = null, fm = null) {
const x1 = fm ? x.map(fm) : x.slice();
const y1 = fm ? y.map(fm) : y.slice();
return hasSubsequence(x1.sort(), y1.sort(), fc);
// return hasSubsequence<T|U>(x1.sort(), y1.sort(), fc, fm);
}
/**
* Obtain all possible prefixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [[], x[..1], x[..2], ...] if n<0; [x[..n]] otherwise
*/ export function prefixes(x, n = -1) {
return [
...iprefixes(x, n)
];
}
/**
* List all possible prefixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [], x[..1], x[..2], ... if n<0; x[..n] otherwise
*/ export function* iprefixes(x, n = -1) {
const X = x.length;
if (n > X) return;
if (n >= 0) {
yield x.slice(0, n);
return;
}
for(let i = 0; i <= X; ++i)yield x.slice(0, i);
}
/**
* Obtain all possible suffixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [x[0..], x[1..], x[2..], ...] if n<0; [x[-n..]] otherwise
*/ export function suffixes(x, n = -1) {
return [
...isuffixes(x, n)
];
}
/**
* List all possible suffixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns x[0..], x[1..], x[2..], ... if n<0; x[-n..] otherwise
*/ export function* isuffixes(x, n = -1) {
const X = x.length;
if (n > X) return;
if (n >= 0) {
yield x.slice(x.length - n);
return;
}
for(let i = 0; i <= X; ++i)yield x.slice(i);
}
/**
* Obtain all possible infixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [[], x[0..1], x[0..2], ..., x[1..2], ...] if n<0; [only of length n] otherwise
*/ export function infixes(x, n = -1) {
return [
...iinfixes(x, n)
];
}
/**
* List all possible infixes.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [], x[0..1], x[0..2], ..., x[1..2], ... if n<0; only of length n otherwise
*/ export function iinfixes(x, n = -1) {
if (n >= 0) return infixesFixed(x, n);
else return infixesAll(x);
}
function* infixesFixed(x, n) {
const X = x.length;
if (n > X) return;
if (n === 0) {
yield [];
return;
}
for(let i = 0, I = X - n + 1; i < I; ++i)yield x.slice(i, i + n);
}
function* infixesAll(x) {
const X = x.length;
yield [];
for(let i = 0; i < X; ++i){
for(let j = i + 1; j <= X; ++j)yield x.slice(i, j);
}
}
/**
* Obtain all possible subsequences.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [elements selected by bit from 0..2^|x|] if n<0; [only of length n] otherwise
*/ export function subsequences(x, n = -1) {
return [
...isubsequences(x, n)
];
}
/**
* List all possible subsequences.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns elements selected by bit from 0..2^|x| if n<0; only of length n otherwise
*/ export function* isubsequences(x, n = -1) {
const X = x.length;
if (n > X) return;
if (n === X) {
yield x;
return;
}
if (n === 0 || X === 0) {
yield [];
return;
}
const y = x.slice(0, -1);
yield* isubsequences(y, n);
for (const s of isubsequences(y, n - 1)){
s.push(x[X - 1]);
yield s;
}
}
/**
* Obtain all possible permutations.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [[], arrangements of length 1, of length 2, ...] if n<0; [only of length n] otherwise
*/ export function permutations(x, n = -1) {
return [
...ipermutations(x, n)
];
}
/**
* List all possible permutations.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @returns [], arrangements of length 1, of length 2, ... if n<0; only of length n otherwise
*/ export function* ipermutations(x, n = -1) {
const X = x.length;
if (n > X) return;
let i = n < 0 ? 0 : n;
const I = n < 0 ? X : n;
for(; i <= I; ++i)yield* ipermutationsFixed(x, i);
}
function* ipermutationsFixed(x, n) {
const X = x.length;
if (X === 0 || n === 0) {
yield [];
return;
}
for(let i = 0; i < X; ++i){
const y = splice(x, i, 1);
for (const p of ipermutationsFixed(y, n - 1))yield [
x[i],
...p
];
}
}
/**
* Find first index of an infix.
* @param x an array
* @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) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length, Y = y.length;
for(let i = 0; i <= X - Y; ++i)if (isInfixAt(x, y, i, fc, fm)) return i;
return -1;
}
/**
* Find last index of an infix.
* @param x an array
* @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) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const X = x.length, Y = y.length;
for(let i = X - Y; i >= 0; --i)if (isInfixAt(x, y, i, fc, fm)) return i;
return -1;
}
/**
* Find indices of an infix.
* @param x an array
* @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 X = x.length, Y = y.length, a = [];
for(let i = 0; i <= X - Y; ++i)if (isInfixAt(x, y, i, fc, fm)) a.push(i);
return a;
}
function isInfixAt(x, y, i, fc, fm) {
const Y = y.length;
for(let j = 0; j < Y; ++j){
const wx = fm(x[i + j], i + j, x);
const wy = fm(y[j], j, y);
if (fc(wx, wy) !== 0) return false;
}
return true;
}
/**
* Find first index of a subsequence.
* @param x an array
* @param y search subsequence
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns begin index of subsequence, -1 if not found
*/ export function searchSubsequence(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...y
].map(fm), Y = y1.length;
let a = -1, i = -1, j = 0;
for (const vx of x){
const wx = fm(vx, ++i, x);
if (fc(wx, y1[j]) !== 0) continue;
if (a < 0) a = i;
if (++j >= Y) return a;
}
return -1;
}
// #endregion
// #region RANDOM ARRANGEMENTS
// ---------------------------
/**
* Pick an arbitrary value.
* @param x an array
* @param fr random number generator ([0, 1))
* @returns x[i] | i ∈ 0..|x|
*/ export function randomValue(x, fr = Math.random) {
fr = fr || Math.random;
const i = Math.floor(fr() * x.length);
return x[i];
}
export { randomValue as value }; // DEPRECATED
/**
* Pick an arbitrary prefix.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x[..i] if n<0; x[..n] otherwise | i ∈ 0..|x|
*/ export function randomPrefix(x, n = -1, fr = Math.random) {
fr = fr || Math.random;
const X = x.length;
if (n > X) return null;
n = n >= 0 ? n : Math.floor((X + 1) * fr());
return x.slice(0, n);
}
export { randomPrefix as prefix }; // DEPRECATED
/**
* Pick an arbitrary suffix.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x[|x|-i..] if n<0; x[|x|-n..] otherwise | i ∈ 0..|x|
*/ export function randomSuffix(x, n = -1, fr = Math.random) {
const X = x.length;
if (n > X) return null;
n = n >= 0 ? n : Math.floor((X + 1) * fr());
return x.slice(X - n);
}
export { randomSuffix as suffix }; // DEPRECATED
/**
* Pick an arbitrary infix.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x[i..j] if n<0; x[i..i+n] otherwise | i, j ∈ 0..|x|
*/ export function randomInfix(x, n = -1, fr = Math.random) {
const X = x.length;
if (n > X) return null;
n = n >= 0 ? n : randomInfixLength(X, fr());
const i = Math.floor((X + 1 - n) * fr());
return x.slice(i, i + n);
}
export { randomInfix as infix }; // DEPRECATED
// Not all infix lengths are equally proable.
function randomInfixLength(X, r) {
const C = 0.5 * X * (X + 1) + 1;
const n = 0.5 * Math.sqrt(1 + 8 * r * C) - 0.5;
return X + 1 - Math.floor(n + 1);
}
/**
* Pick an arbitrary subsequence.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x[i, j, ...] | [i, j, ...] = is; |is| = |x| if n<0 else n
*/ export function randomSubsequence(x, n = -1, fr = Math.random) {
const X = x.length;
if (n > X) return null;
if (n >= 0) return randomSubsequenceFixed(x, n, fr);
else return randomSubsequenceAll(x, fr);
}
export { randomSubsequence as subsequence }; // DEPRECATED
function randomSubsequenceFixed(x, n, fr) {
const is = fromRange(0, x.length);
randomPermutation$(is, n, fr).sort();
return getAll(x, is);
}
function randomSubsequenceAll(x, fr) {
const a = [];
for (const v of x)if (fr() < 0.5) a.push(v);
return a;
}
/**
* Pick an arbitrary permutation.
* @param x an array
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x' | x' = x; values are randomly shuffled
*/ export function randomPermutation(x, n = -1, fr = Math.random) {
const X = x.length;
if (n > X) return null;
return randomPermutation$(x.slice(), n, fr);
}
export { randomPermutation as permutation }; // DEPRECATED
/**
* Pick an arbitrary permutation!
* @param x an array (updated!)
* @param n number of values [-1 ⇒ any]
* @param fr random number generator ([0, 1))
* @returns x | values are randomly shuffled
*/ export function randomPermutation$(x, n = -1, fr = Math.random) {
fr = fr || Math.random;
const X = x.length;
if (n > X) return x;
n = n >= 0 ? n : Math.floor((X + 1) * fr());
for(let i = 0; i < n; ++i){
const j = i + Math.floor((X - i) * fr());
const t = x[i];
x[i] = x[j];
x[j] = t;
}
x.length = n;
return x;
}
export { randomPermutation$ as permutation$ }; // DEPRECATED
export { randomPermutation$ as permute$ };
export { randomPermutation$ as shuffle$ };
// - https://en.wikipedia.org/wiki/Fisher–Yates_shuffle
// #endregion
// #region FIND
// ------------
/**
* Find first value passing a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns first v | ft(v) = true; v ∈ x
*/ export function find(x, ft) {
return x.find(ft);
}
/**
* Find last value passing a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns last v | ft(v) = true; v ∈ x
*/ export function findRight(x, ft) {
for(let i = x.length - 1; i >= 0; --i)if (ft(x[i], i, x)) return x[i];
return undefined;
}
// #endregion
// #region TAKE/DROP
// -----------------
/**
* Keep first n values only.
* @param x an array
* @param n number of values [1]
* @returns x[0..n]
*/ export function take(x, n = 1) {
n = Math.max(n, 0);
return x.slice(0, n);
}
export { take as left };
/**
* Keep last n values only.
* @param x an array
* @param n number of values [1]
* @returns x[0..n]
*/ export function takeRight(x, n = 1) {
const X = x.length;
n = Math.min(Math.max(n, 0), X);
return x.slice(X - n);
}
export { takeRight as right };
/**
* Keep values from left, while a test passes.
* @param x an array
* @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) {
return x.slice(0, scanWhile(x, ft));
}
/**
* Keep values from right, while a test passes.
* @param x an array
* @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) {
return x.slice(scanWhileRight(x, ft));
}
/**
* Discard first n values only.
* @param x an array
* @param n number of values [1]
* @returns x[n..]
*/ export function drop(x, n = 1) {
n = Math.max(n, 0);
return x.slice(n);
}
/**
* Discard last n values only.
* @param x an array
* @param n number of values [1]
* @returns x[0..-n]
*/ export function dropRight(x, n = 1) {
const X = x.length;
n = Math.min(Math.max(n, 0), X);
return x.slice(0, X - n);
}
/**
* Discard values from left, while a test passes.
* @param x an array
* @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) {
return x.slice(scanWhile(x, ft));
}
/**
* Discard values from right, while a test passes.
* @param x an array
* @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) {
return x.slice(0, scanWhileRight(x, ft));
}
// #endregion
// #region SCAN
// ------------
/**
* 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 array
* @param ft test function (v, i, x)
* @returns first index where test passes till end
*/ export function scanWhileRight(x, ft) {
let i = x.length - 1;
for(; i >= 0; --i)if (!ft(x[i], i, x)) break;
return ++i;
}
/**
* 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 array
* @param ft test function (v, i, x)
* @returns first index where test fails till end
*/ export function scanUntilRight(x, ft) {
let i = x.length - 1;
for(; i >= 0; --i)if (ft(x[i], i, x)) break;
return ++i;
}
// #endregion
// #region SEARCH
// --------------
/**
* Find first index of a value.
* @param x an array
* @param v search value
* @param i begin index [0]
* @returns index of v in x[i..] if found else -1
*/ export function indexOf(x, v, i = 0) {
return x.indexOf(v, i);
}
/**
* Find last index of a value.
* @param x an array
* @param v search value
* @param i begin index [|x|-1]
* @returns last index of v in x[0..i] if found else -1
*/ export function lastIndexOf(x, v, i = x.length - 1) {
return x.lastIndexOf(v, i);
}
/**
* Find index of first value passing a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns first index of value, -1 if not found
*/ export function search(x, ft) {
return x.findIndex(ft);
}
export { search as findIndex };
/**
* Find index of last value passing a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns last index of value, -1 if not found
*/ export function searchRight(x, ft) {
for(let i = x.length - 1; i >= 0; --i)if (ft(x[i], i, x)) return i;
return -1;
}
export { searchRight as findLastIndex };
/**
* Find indices of values passing a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns indices of value
*/ export function searchAll(x, ft) {
let i = -1;
const a = [];
for (const v of x)if (ft(v, ++i, x)) a.push(i);
return a;
}
// #endregion
// #region FUNCTIONAL
// ------------------
/**
* Call a function for each value.
* @param x an array
* @param fp process function (v, i, x)
*/ export function forEach(x, fp) {
x.forEach(fp);
}
/**
* Examine if any value satisfies a test.
* @param x an array
* @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 x.some(ft);
else return someBoolean(x);
}
export { some as anyOf };
function someBoolean(x) {
const I = x.length;
for(let i = 0; i < I; ++i)if (x[i]) return true;
return false;
}
/**
* Examine if all values satisfy a test.
* @param x an array
* @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 x.every(ft);
else return everyBoolean(x);
}
export { every as allOf };
function everyBoolean(x) {
const I = x.length;
for(let i = 0; i < I; ++i)if (!x[i]) return false;
return true;
}
/**
* Transform values of an array.
* @param x an array
* @param fm map function (v, i, x)
* @returns [fm(v₀), fm(v₁), ...] | vᵢ ∈ x
*/ export function map(x, fm) {
return x.map(fm);
}
/**
* Transform values of an array!
* @param x an array (updated!)
* @param fm map function (v, i, x)
* @returns x = [fm(v₀), fm(v₁), ...]; vᵢ ∈ x
*/ export function map$(x, fm) {
const I = x.length;
for(let i = 0; i < I; ++i)x[i] = fm(x[i], i, x);
return x;
}
/**
* Reduce values of array to a single value.
* @param x an array
* @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) {
const init = arguments.length <= 2;
return init ? x.reduce(fr) : x.reduce(fr, acc);
}
/**
* Reduce values from right, to a single value.
* @param x an array
* @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 reduceRight(x, fr, acc) {
let init = arguments.length <= 2;
for(let i = x.length - 1; i >= 0; --i){
if (init) {
acc = x[i];
init = false;
} else acc = fr(acc, x[i], i, x);
}
return acc;
}
/**
* Keep values which pass a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns [v₀, v₁, ...] | ft(vᵢ) = true; vᵢ ∈ x
*/ export function filter(x, ft) {
return x.filter(ft);
}
export { filter as findAll };
/**
* Keep values which pass a test!
* @param x an array (updated!)
* @param ft test function (v, i, x)
* @returns x = [v₀, v₁, ...] | ft(vᵢ) = true; vᵢ ∈ x
*/ export function filter$(x, ft) {
const I = x.length;
let j = 0;
for(let i = 0; i < I; ++i)if (ft(x[i], i, x)) x[j++] = x[i];
x.length = j;
return x;
}
/**
* Keep values at given indices.
* @param x an array
* @param is indices
* @returns v₀, v₁, ... | vᵢ = x[i]; i ∈ is
*/ export function filterAt(x, is) {
const X = x.length;
const a = [];
for (const i of is)if (i >= 0 && i < X) a.push(x[i]);
return a;
}
/**
* Discard values which pass a test.
* @param x an array
* @param ft test function (v, i, x)
* @returns [v₀, v₁, ...] | ft(vᵢ) = false; vᵢ ∈ x
*/ export function reject(x, ft) {
let i = -1;
const a = [];
for (const v of x)if (!ft(v, ++i, x)) a.push(v);
return a;
}
/**
* Discard values which pass a test!
* @param x an array (updated!)
* @param ft test function (v, i, x)
* @returns x = [v₀, v₁, ...] | ft(vᵢ) = false; vᵢ ∈ x
*/ export function reject$(x, ft) {
const I = x.length;
let j = 0;
for(let i = 0; i < I; ++i)if (!ft(x[i], i, x)) x[j++] = x[i];
x.length = j;
return x;
}
/**
* Discard values at given indices.
* @param x an array
* @param is indices
* @returns [v₀, v₁, ...] | vᵢ = x[i]; i ∉ is
*/ export function rejectAt(x, is) {
let i = -1;
const a = [];
for (const v of x)if (!is.includes(++i)) a.push(v);
return a;
}
// #endregion
// #region FLATTEN
// ---------------
/**
* Flatten nested array to given depth.
* @param x a nested array
* @param n maximum depth [-1 ⇒ all]
* @param fm map function (v, i, x)
* @param ft flatten test function (v, i, x) [is]
* @returns flat iterable
*/ export function flat(x, n = -1, fm = null, ft = null) {
fm = fm || IDENTITY;
ft = ft || is;
return flatTo$([], x, n, fm, ft);
}
function flatTo$(a, x, n, fm, ft) {
let i = -1;
for (const v of x){
const w = fm(v, ++i, x);
if (n !== 0 && ft(w, i, x)) flatTo$(a, v, n - 1, fm, ft);
else a.push(w);
}
return a;
}
/**
* Flatten nested array, based on map function.
* @param x an array
* @param fm map function (v, i, x)
* @param ft flatten test function (v, i, x) [is]
* @returns flat iterable
*/ export function flatMap(x, fm = null, ft = null) {
fm = fm || IDENTITY;
ft = ft || is;
let i = -1;
const a = [];
for (const v of x){
const w = fm(v, ++i, x);
if (ft(w, i, x)) concat$(a, w);
else a.push(w);
}
return a;
}
// #endregion
// #region PREFIX SUM
// ------------------
/**
* Perform exclusive prefix scan from left to right.
* @param x an array
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns [acc, fr(acc, v₀), fr(fr(acc, v₀), v₁)...]
*/ export function exclusiveScan(x, fr, acc) {
const a = [];
const I = x.length;
for(let i = 0; i < I; ++i){
a.push(acc);
acc = fr(acc, x[i], i, x);
}
return a;
}
/**
* Perform exclusive prefix scan from left to right!
* @param x an array (updated!)
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns x = [acc, fr(acc, v₀), fr(fr(acc, v₀), v₁)...]
*/ export function exclusiveScan$(x, fr, acc) {
const I = x.length;
for(let i = 0; i < I; ++i){
const v = x[i];
x[i] = acc;
acc = fr(acc, v, i, x);
}
return x;
}
/**
* Perform inclusive prefix scan from left to right.
* @param x an array
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns [fr(acc, v₀), fr(fr(acc, v₀), v₁)...]
*/ export function inclusiveScan(x, fr, acc) {
let init = arguments.length <= 2;
const a = [];
const I = x.length;
for(let i = 0; i < I; ++i){
acc = init ? x[i] : fr(acc, x[i], i, x);
a.push(acc);
init = false;
}
return a;
}
export { inclusiveScan as accumulate };
/**
* Perform inclusive prefix scan from left to right!
* @param x an array (updated!)
* @param fr reduce function (acc, v, i, x)
* @param acc initial value
* @returns x = [fr(acc, v₀), fr(fr(acc, v₀), v₁)...]
*/ export function inclusiveScan$(x, fr, acc) {
const I = x.length;
for(let i = 0; i < I; ++i)acc = x[i] = fr(acc, x[i], i, x);
return x;
}
/**
* Combine adjacent values of an array.
* @param x an array
* @param fc combine function (u, v)
* @param acc initial value
* @returns [fc(acc, v₀), fc(v₀, v₁)...] | vᵢ ∈ x
*/ export function adjacentCombine(x, fc, acc) {
const a = [];
if (x.length > 0) a.push(fc(acc, x[0]));
const I = x.length;
for(let i = 1; i < I; ++i)a.push(fc(x[i - 1], x[i]));
return a;
}
// adjacentMap()?
/**
* Combine adjacent values of an array!
* @param x an array (updated!)
* @param fc combine function (u, v)
* @param acc initial value
* @returns x = [fc(acc, v₀), fc(v₀, v₁)...] | vᵢ ∈ x
*/ export function adjacentCombine$(x, fc, acc) {
const X = x.length;
if (X === 0) return x;
let v = x[0];
x[0] = fc(acc, v);
for(let i = 1; i < X; ++i){
const w = x[i];
x[i] = fc(v, w);
v = w;
}
return x;
}
// #endregion
// #region COMBINE
// ---------------
/**
* Place a separator between every value.
* @param x an array
* @param v separator
* @returns [x[0], v, x[1], v, ..., x[|x|-1]]
*/ export function intersperse(x, v) {
const a = [];
let i = -1;
for (const u of x){
if (++i > 0) a.push(v);
a.push(u);
}
return a;
}
/**
* Estimate new values between existing ones.
* @param x an array
* @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) {
const a = [];
let u = undefined;
let i = -1;
for (const v of x){
if (++i > 0) a.push(fc(u, v));
a.push(u = v);
}
return a;
}
/**
* Place values of an array between another.
* @param x an array
* @param y another array
* @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 X = x.length;
const Y = y.length;
const a = [];
m = Math.max(m, 0);
n = Math.max(n, 0);
s = Math.max(s, 1);
t = Math.max(t, 1);
for(let i = 0, j = 0; i < X; i += s){
if (i > 0) {
for(let k = j, K = k + n; k < K; ++k)a.push(y[k % Y]);
j += t;
}
concat$(a, x.slice(i, i + m));
}
return a;
}
/**
* Place values from iterables alternately.
* @param xs arrays
* @returns [x₀[0], x₁[0], ..., x₀[1], x₁[0], ...] | [x₀, x₁, ...] = xs
*/ export function interleave(xs) {
const a = [];
for(let i = 0;; ++i){
let n = 0;
for (const x of xs)if (i < x.length) {
a.push(x[i]);
++n;
}
if (n === 0) break;
}
return a;
}
/**
* Combine values from arrays.
* @param xs arrays
* @param fm map function (vs, i)
* @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, a = [];
if (X === 0) return a;
const ds = new Array(X).fill(false);
const ls = xs.map((x)=>x.length);
for(let i = 0;; ++i){
const vs = [];
for(let j = 0; j < X; ++j){
ds[j] = i >= ls[j];
vs[j] = ds[j] ? vd : xs[j][i];
}
if (fe(ds)) break;
a.push(fm(vs, i, null));
}
return a;
}
// TODO: zip2()?
// #endregion
// #region MANIPULATION
// --------------------
/**
* Fill with given value.
* @param x an array
* @param v value
* @param i begin index [0]
* @param I end index [|x|]
* @returns x' | x' = x; x'[i..I] = v
*/ export function fill(x, v, i = 0, I = x.length) {
return x.slice().fill(v, i, I);
}
/**
* Fill with given value!
* @param x an array (updated!)
* @param v value
* @param i begin index [0]
* @param I end index [|x|]
* @returns x | x[i..I] = v
*/ export function fill$(x, v, i = 0, I = x.length) {
return x.fill(v, i, I);
}
/**
* Add value to the end.
* @param x an array
* @param vs values to add
* @returns x ⧺ vs
*/ export function push(x, ...vs) {
return x.concat(vs);
}
export { push as pushBack };
export { push as append };
/**
* Add values to the end!
* @param x an array (updated!)
* @param vs values to add
* @returns x = x ⧺ vs
*/ export function push$(x, ...vs) {
x.push(...vs);
return x;
}
export { push$ as pushBack$ };
export { push$ as append$ };
/**
* Remove last value.
* @param x an array
* @returns x[0..|x|-1]
*/ export function pop(x) {
return x.slice(0, -1);
}
export { pop as popBack };
/**
* Remove last value!
* @param x an array (updated!)
* @returns x = x[0..|x|-1]
*/ export function pop$(x) {
x.pop();
return x;
}
export { pop as popBack$ };
/**
* Remove first value.
* @param x an array
* @returns x[1..]
*/ export function shift(x) {
return x.slice(1);
}
export { shift as popFront };
/**
* Remove first value!
* @param x an array (updated!)
* @returns x = x[1..]
*/ export function shift$(x) {
x.shift();
return x;
}
export { shift$ as popFront$ };
/**
* Add values to the start.
* @param x an array
* @param vs values to add
* @returns vs ⧺ x
*/ export function unshift(x, ...vs) {
return concat$(vs, x);
}
export { unshift as pushFront };
export { unshift as prepend };
/**
* Add values to the start!
* @param x an array (updated!)
* @param vs values to add
* @returns x = vs ⧺ x
*/ export function unshift$(x, ...vs) {
x.unshift(...vs);
return x;
}
export { unshift$ as pushFront$ };
export { unshift$ as prepend$ };
/**
* Copy part of array to another.
* @param x target array
* @param y source array
* @param j write index [0]
* @param i read begin index [0]
* @param I read end index [|x|]
* @returns x[0..j] ⧺ y[i..I] ⧺ x[j+I-i..]
*/ export function copy(x, y, j = 0, i = 0, I = y.length) {
return copy$(x.slice(), y, j, i, I);
}
/**
* Copy part of array to another!
* @param x target array (updated!)
* @param y source array
* @param j write index [0]
* @param i read begin index [0]
* @param I read end index [|x|]
* @returns x = x[0..j] ⧺ y[i..I] ⧺ x[j+I-i..]
*/ export function copy$(x, y, j = 0, i = 0, I = y.length) {
j = index(x, j);
[i, I] = indexRange(y, i, I);
for(; i < I; ++i, ++j)x[j] = y[i];
return x;
}
/**
* Copy part of array within.
* @param x an array
* @param j write index [0]
* @param i read begin index [0]
* @param I read end index [|x|]
* @returns x[0..j] ⧺ x[i..I] ⧺ x[j+I-i..]
*/ export function copyWithin(x, j = 0, i = 0, I = x.length) {
return x.slice().copyWithin(j, i, I);
}
/**
* Copy part of array within!
* @param x an array (updated!)
* @param j write index [0]
* @param i read begin index [0]
* @param I read end index [|x|]
* @returns x = x[0..j] ⧺ x[i..I] ⧺ x[j+I-i..]
*/ export function copyWithin$(x, j = 0, i = 0, I = x.length) {
return x.copyWithin(j, i, I);
}
/**
* Move part of array within.
* @param x an array
* @param j write index [0]
* @param i read begin index [0]
* @param I read end index [|x|]
* @returns x[0..j] ⧺ x[i..I] ⧺ x[j..i] ⧺ x[I..]
*/ export function moveWithin(x, j = 0, i = 0, I = x.length) {
j = index(x, j);
[i, I] = indexRange(x, i, I);
if (j < i) return movePart(x, j, i, I);
else return movePart(x, i, I, j);
}
function movePart(x, i, j, k) {
return x.slice(0, i).concat(x.slice(j, k), x.slice(i, j), x.slice(k));
}
/**
* Move part of array within!
* @param x an array (updated!)
* @param j write ±index [0]
* @param i read begin ±index [0]
* @param I read end ±index [|x|]
* @returns x = x[0..j] ⧺ x[i..I] ⧺ x[j..i] ⧺ x[I..]
*/ export function moveWithin$(x, j = 0, i = 0, I = x.length) {
j = index(x, j);
[i, I] = indexRange(x, i, I);
const p = x.slice(i, I), P = p.length;
if (j < i) x.copyWithin(j + P, j, i);
else x.copyWithin(i, I, j);
return copy$(x, p, j < i ? j : j - P);
}
// DOUBT: Are negative indices any helpful (other than basic shortcuts)?
// DOUBT: It is not easy to use a negative index supporting function from another negative index supporting function.
// DOUBT: Seems to me they are only complicating implementation of algorithms, and should be removed.
/**
* Remove or replace existing values.
* @param x an array
* @param i remove ±index
* @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, n = x.length, ...vs) {
i = index(x, i);
n = Math.max(n, 0);
return concat$(x.slice(0, i), vs, x.slice(i + n));
}
export { splice as toSpliced };
/**
* Remove or replace existing values!
* @param x an array (updated!)
* @param i remove ±index
* @param n number of values to remove [rest]
* @param vs values to insert
* @returns x = x[0..i] ⧺ vs ⧺ x[i+n..]
*/ export function splice$(x, i, n = x.length, ...vs) {
x.splice(i, n, ...vs);
return x;
}
// #endregion
// #region COUNT/PARTITION
// -----------------------
/**
* Count values which satisfy a test.
* @param x an array
* @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 each distinct value.
* @param x an array
* @param fm map function (v, i, x)
* @returns Map \{value ⇒ count\}
*/ export function countEach(x, fm = null) {
fm = fm || IDENTITY;
let i = -1;
const a = new Map();
for (const v of x){
const w = fm(v, ++i, x);
a.set(w, (a.get(w) || 0) + 1);
}
return a;
}
export { countEach as countAs }; // DEPRECATED
/**
* 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 each distinct value.
* @param x an array
* @param fm map function (v, i, x)
* @returns Map \{key ⇒ values\}
*/ export function partitionEach(x, fm = null) {
fm = fm || IDENTITY;
let i = -1;
const a = new Map();
for (const v of x){
const w = fm(v, ++i, x);
if (!a.has(w)) a.set(w, []);
a.get(w).push(v);
}
return a;
}
export { partitionEach as groupToMap };
export { partitionEach as partitionAs }; // DEPRECATED
// #endregion
// #region SPLITS
// --------------
/**
* Break array considering test as separator.
* @param x an array
* @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 i = -1;
const a = [];
let b = [];
for (const v of x){
if (!ft(v, ++i, x)) b.push(v);
else if (b.length) {
a.push(b);
b = [];
}
}
if (b.length) a.push(b);
return a;
}
/**
* Break array considering indices as separator.
* @param x an array
* @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 i = -1;
const a = [];
let b = [];
for (const v of x){
if (!is.includes(++i)) b.push(v);
else if (b.length) {
a.push(b);
b = [];
}
}
if (b.length) a.push(b);
return a;
}
/**
* Break array when test passes.
* @param x an array
* @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 j = 0;
const a = [];
const I = x.length;
for(let i = 0; i < I; ++i){
if (!ft(x[i], i, x)) continue;
a.push(x.slice(j, i));
j = i;
}
a.push(x.slice(j));
return a;
}
/**
* Break array after test passes.
* @param x an array
* @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 j = 0;
const a = [];
const I = x.length;
for(let i = 0; i < I; ++i){
if (!ft(x[i], i, x)) continue;
a.push(x.slice(j, i + 1));
j = i + 1;
}
a.push(x.slice(j));
return a;
}
/**
* Break array at given indices.
* @param x an array
* @param is split ±indices (left to right)
* @returns [x[0..j], x[j..k], ...] | ft(x[i]) = true; i = j, k, ...; i ∈ is
*/ export function cutAt(x, is) {
const X = x.length;
let j = 0;
const a = [];
for (let i of is){
i = i < 0 ? X + i : i;
a.push(x.slice(j, i));
j = Math.max(j, i);
}
a.push(x.slice(j));
return a;
}
/**
* Break array after given indices.
* @param x an array
* @param is split ±indices (left to right)
* @returns [x[0..j+1], x[j+1..k], ...] | ft(x[i]) = true; i = j, k, ...; i ∈ is
*/ export function cutAtRight(x, is) {
const X = x.length;
let j = 0;
const a = [];
for (let i of is){
i = i < 0 ? X + i : i;
a.push(x.slice(j, i + 1));
j = Math.max(j, i + 1);
}
a.push(x.slice(j));
return a;
}
/**
* Keep similar values together and in order.
* @param x an array
* @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;
const a = [];
let b = [];
let u = undefined, i = -1;
for (const v of x){
const w = fm(v, ++i, x);
if (i === 0 || fc(u, w) === 0) b.push(v);
else {
a.push(b);
b = [
v
];
}
u = w;
}
a.push(b);
return a;
}
/**
* Break array into chunks of given size.
* @param x an array
* @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 a = [];
if (n < 0) return a;
s = Math.max(s, 1);
const I = x.length;
for(let i = 0; i < I; i += s)a.push(x.slice(i, i + n));
return a;
}
// #endregion
// #region CONCAT/JOIN
// -------------------
/**
* Append values from arrays.
* @param xs arrays
* @returns x₀ ⧺ x₁ ⧺ ... | [x₀, x₁, ...] = xs
*/ export function concat(...xs) {
return [].concat(...xs);
}
/**
* Append values from arrays!
* @param x an array (updated!)
* @param ys arrays to append
* @returns x = x ⧺ y₀ ⧺ y₁ ⧺ ...] | [y₀, y₁, ...] = ys
*/ export function concat$(x, ...ys) {
for (const y of ys)x.push(...y);
return x;
}
/**
* Join values together into a string.
* @param x an array
* @param sep separator [,]
* @returns "$\{v₀\}$\{sep\}$\{v₁\}..." | vᵢ ∈ x
*/ export function join(x, sep = ",") {
return x.join(sep);
}
// #endregion
// #region REARRANGE
// -----------------
/**
* Obtain values that cycle through array.
* @param x an array
* @param i begin ±index [0]
* @param n number of values [|x|]
*/ export function cycle(x, i = 0, n = x.length) {
const X = x.length;
if (n <= 0 || X === 0) return [];
i = mod(i, X);
const a = x.slice(i, i + n);
n -= a.length;
const M = Math.floor(n / X);
for(let m = 0; m < M; ++m)concat$(a, x);
return concat$(a, x.slice(0, n % X));
}
/**
* Repeat an array given times.
* @param x an array
* @param n times [1]
* @returns x ⧺ x ⧺ ...(n times)
*/ export function repeat(x, n = 1) {
const a = [];
for(; n > 0; --n)concat$(a, x);
return a;
}
/**
* Reverse the values.
* @param x an array
* @returns [x[|x|-1], x[|x|-2], ..., x[1], x[0]]
*/ export function reverse(x) {
return x.slice().reverse();
}
export { reverse as toReversed };
/**
* Reverse the values!
* @param x an array (updated!)
* @returns x = [x[|x|-1], x[|x|-2], ..., x[1], x[0]]
*/ export function reverse$(x) {
return x.reverse();
}
/**
* Rotate values in array.
* @param x an array
* @param n rotate amount (+ve: left, -ve: right) [0]
* @returns x[n..] ⧺ x[0..n]
*/ export function rotate(x, n = 0) {
n = mod(n, x.length);
return concat$(x.slice(n), x.slice(0, n));
}
/**
* Rotate values in array!
* @param x an array (updated!)
* @param n rotate amount (+ve: left, -ve: right) [0]
* @returns x = x[n..] ⧺ x[0..n]
*/ export function rotate$(x, n = 0) {
n = mod(n, x.length);
const y = x.slice(0, n);
x.copyWithin(0, n);
return copy$(x, y, x.length - n);
}
// #endregion
// #region SET OPERATIONS
// ------------------------
/**
* Examine 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 s = new Set();
let i = -1;
for (const v of x){
const w = fm(v, ++i, x);
if (s.has(w)) return false;
s.add(w);
}
return true;
}
function isUniqueDual(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const x1 = [
...x
].map(fm);
for (const wx of x1){
for (const wy of x1)if (fc(wx, wy) === 0) return false;
}
return true;
}
/**
* Examine 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) {
fm = fm || IDENTITY;
const s = toSet(y, fm);
let i = -1;
for (const v of x){
const w = fm(v, ++i, x);
if (s.has(w)) return false;
}
return true;
}
function isDisjointDual(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...y
].map(fm);
let i = -1;
for (const vx of x){
const wx = fm(vx, ++i, x);
for (const wy of y1)if (fc(wx, wy) === 0) return false;
}
return true;
}
/**
* Remove duplicate values.
* @param x an array
* @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) return uniqueDual(x, fc, fm);
else return uniqueMap(x, fm);
}
function uniqueMap(x, fm = null) {
fm = fm || IDENTITY;
const s = new Set();
let i = -1;
const a = [];
for (const v of x){
const w = fm(v, ++i, x);
if (s.has(w)) continue;
s.add(w);
a.push(v);
}
return a;
}
function uniqueDual(x, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
let i = -1;
const s = [], a = [];
x: for (const vx of x){
const wx = fm(vx, ++i, x);
for (const ws of s)if (fc(ws, wx) === 0) continue x;
s.push(wx);
a.push(vx);
}
return a;
}
/**
* Obtain values present in any array.
* @param x an array
* @param y another array
* @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) {
return union$(x.slice(), y, fc, fm);
}
/**
* Obtain values present in any array!
* @param x an array (updated!)
* @param y another array
* @param fc compare function (a, b)
* @param fm map function (v, i, x)
* @returns x = x ∪ y = \{v | v ∈ x or v ∈ y\}
*/ export function union$(x, y, fc = null, fm = null) {
if (fc) return unionDual$(x, y, fc, fm);
else return unionMap$(x, y, fm);
}
function unionMap$(x, y, fm = null) {
fm = fm || IDENTITY;
const s = toSet(x, fm);
let i = -1;
for (const vy of y){
const wy = fm(vy, ++i, y);
if (!s.has(wy)) x.push(vy);
}
return x;
}
function unionDual$(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const x1 = x.map(fm);
let i = -1;
y: for (const vy of y){
const wy = fm(vy, ++i, y);
for (const wx of x1)if (fc(wx, wy) === 0) continue y;
x.push(vy);
}
return x;
}
/**
* Obtain values present in both arrays.
* @param x an array
* @param y another array
* @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) return intersectionDual(x, y, fc, fm);
else return intersectionMap(x, y, fm);
}
function intersectionMap(x, y, fm = null) {
fm = fm || IDENTITY;
const s = toSet(y, fm);
let i = -1;
const a = [];
for (const vx of x){
const wx = fm(vx, ++i, x);
if (s.has(wx)) a.push(vx);
}
return a;
}
function intersectionDual(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...y
].map(fm);
let i = -1;
const a = [];
x: for (const vx of x){
const wx = fm(vx, ++i, x);
for (const wy of y1)if (fc(wx, wy) === 0) {
a.push(vx);
continue x;
}
}
return a;
}
/**
* Obtain values not present in another array.
* @param x an array
* @param y another array
* @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) return differenceDual(x, y, fc, fm);
else return differenceMap(x, y, fm);
}
function differenceMap(x, y, fm = null) {
fm = fm || IDENTITY;
const s = toSet(y, fm);
let i = -1;
const a = [];
for (const vx of x){
const wx = fm(vx, ++i, x);
if (!s.has(wx)) a.push(vx);
}
return a;
}
function differenceDual(x, y, fc = null, fm = null) {
fc = fc || COMPARE;
fm = fm || IDENTITY;
const y1 = [
...y
].map(fm);
let i = -1;
const a = [];
x: for (const vx of x){
const wx = fm(vx, ++i, x);
for (const wy of y1)if (fc(wx, wy) === 0) continue x;
a.push(vx);
}
return a;
}
/**
* Obtain values not present in both arrays.
* @param x an array
* @param y another array
* @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) {
const x0 = fromIterable$(x);
const y0 = fromIterable$(y);
const ax = difference(x0, y0, fc, fm);
const ay = difference(y0, x0, fc, fm);
return concat$(ax, ay);
}
/**
* Obtain cartesian product of arrays.
* @param xs arrays
* @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 XS = xs.length;
const a = [];
if (XS === 0) return a;
const is = new Array(XS).fill(0);
const ls = xs.map((x)=>x.length);
if (ls.some((l)=>l === 0)) return a;
for(let i = 0;; ++i){
const vs = [];
for(let j = 0; j < XS; ++j)vs.push(xs[j][is[j]]);
a.push(fm(vs, i, null));
let r = XS - 1;
for(; r >= 0; --r){
if (++is[r] < ls[r]) break;
is[r] = 0;
}
if (r < 0) break;
}
return a;
} // #endregion
// #endregion
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9leHRyYS1hcnJheS9leHRyYS1hcnJheS9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyAjcmVnaW9uIFRZUEVTXG4vLyA9PT09PT09PT09PT09XG5cbi8qKiBFbnRyaWVzIGlzIGFuIGFycmF5IG9mIGluZGV4LXZhbHVlIHBhaXJzLCB3aXRoIHVuaXF1ZSBpbmRpY2VzLiAqL1xuZXhwb3J0IHR5cGUgRW50cmllczxUPiA9IFtudW1iZXIsIFRdW107XG4vKiogSUVudHJpZXMgaXMgYSBsaXN0IG9mIGluZGV4LXZhbHVlIHBhaXJzLCB3aXRoIHVuaXF1ZSBpbmRpY2VzLiAqL1xuZXhwb3J0IHR5cGUgSUVudHJpZXM8VD4gPSBJdGVyYWJsZTxbbnVtYmVyLCBUXT47XG5cblxuLyoqIExpc3RzIGlzIGEgcGFpciBvZiBpbmRleCBhcnJheSBhbmQgdmFsdWUgYXJyYXksIHdpdGggdW5pcXVlIGluZGljZXMuICovXG5leHBvcnQgdHlwZSBMaXN0czxUPiA9IFtudW1iZXJbXSwgVFtdXTtcbi8qKiBJTGlzdHMgaXMgYSBwYWlyIG9mIGluZGV4IGl0ZXJhYmxlIGxpc3QgYW5kIHZhbHVlIGl0ZXJhYmxlIGxpc3QsIHdpdGggdW5pcXVlIGluZGljZXMuICovXG5leHBvcnQgdHlwZSBJTGlzdHM8VD4gPSBbSXRlcmFibGU8bnVtYmVyPiwgSXRlcmFibGU8VD5dO1xuXG5cbi8qKlxuICogSGFuZGxlIHJlYWRpbmcgb2YgYSBzaW5nbGUgdmFsdWUuXG4gKiBAcmV0dXJucyB2YWx1ZVxuICovXG5leHBvcnQgdHlwZSBSZWFkRnVuY3Rpb248VD4gPSAoKSA9PiBUO1xuXG5cbi8qKlxuICogSGFuZGxlIGNvbWJpbmluZyBvZiB0d28gdmFsdWVzLlxuICogQHBhcmFtIGEgYSB2YWx1ZVxuICogQHBhcmFtIGIgYW5vdGhlciB2YWx1ZVxuICogQHJldHVybnMgY29tYmluZWQgdmFsdWVcbiAqL1xuZXhwb3J0IHR5cGUgQ29tYmluZUZ1bmN0aW9uPFQ+ID0gKGE6IFQsIGI6IFQpID0+IFQ7XG5cblxuLyoqXG4gKiBIYW5kbGUgY29tcGFyaXNvbiBvZiB0d28gdmFsdWVzLlxuICogQHBhcmFtIGEgYSB2YWx1ZVxuICogQHBhcmFtIGIgYW5vdGhlciB2YWx1ZVxuICogQHJldHVybnMgYTxiOiAtdmUsIGE9YjogMCwgYT5iOiArdmVcbiAqL1xuZXhwb3J0IHR5cGUgQ29tcGFyZUZ1bmN0aW9uPFQ+ID0gKGE6IFQsIGI6IFQpID0+IG51bWJlcjtcblxuXG4vKipcbiAqIEhhbmRsZSBwcm9jZXNzaW5nIG9mIHZhbHVlcyBpbiBhbiBhcnJheS5cbiAqIEBwYXJhbSB2IHZhbHVlIGluIGFycmF5XG4gKiBAcGFyYW0gaSBpbmRleCBvZiB2YWx1ZSBpbiBhcnJheVxuICogQHBhcmFtIHggYXJyYXkgY29udGFpbmluZyB0aGUgdmFsdWVcbiAqL1xuZXhwb3J0IHR5cGUgUHJvY2Vzc0Z1bmN0aW9uPFQ+ID0gKHY6IFQsIGk6IG51bWJlciwgeDogVFtdIHwgbnVsbCkgPT4gdm9pZDtcblxuXG4vKipcbiAqIEhhbmRsZSBzZWxlY3Rpb24gb2YgdmFsdWVzIGluIGFuIGFycmF5LlxuICogQHBhcmFtIHYgdmFsdWUgaW4gYXJyYXlcbiAqIEBwYXJhbSBpIGluZGV4IG9mIHZhbHVlIGluIGFycmF5XG4gKiBAcGFyYW0geCBhcnJheSBjb250YWluaW5nIHRoZSB2YWx1ZVxuICogQHJldHVybnMgc2VsZWN0ZWQ/XG4gKi9cbmV4cG9ydCB0eXBlIFRlc3RGdW5jdGlvbjxUPiA9ICh2OiBULCBpOiBudW1iZXIsIHg6IFRbXSB8IG51bGwpID0+IGJvb2xlYW47XG5cblxuLyoqXG4gKiBIYW5kbGUgdHJhbnNmb3JtYXRpb24gb2YgYSB2YWx1ZSB0byBhbm90aGVyLlxuICogQHBhcmFtIHYgdmFsdWUgaW4gYXJyYXlcbiAqIEBwYXJhbSBpIGluZGV4IG9mIHZhbHVlIGluIGFycmF5XG4gKiBAcGFyYW0geCBhcnJheSBjb250YWluaW5nIHRoZSB2YWx1ZVxuICogQHJldHVybnMgdHJhbnNmb3JtZWQgdmFsdWVcbiAqL1xuZXhwb3J0IHR5cGUgTWFwRnVuY3Rpb248VCwgVT4gPSAodjogVCwgaTogbnVtYmVyLCB4OiBUW10gfCBudWxsKSA9PiBVO1xuXG5cbi8qKlxuICogSGFuZGxlIHJlZHVjdGlvbiBvZiBtdWx0aXBsZSB2YWx1ZXMgaW50byBhIHNpbmdsZSB2YWx1ZS5cbiAqIEBwYXJhbSBhY2MgYWNjdW11bGF0b3IgKHRlbXBvcmFyeSByZXN1bHQpXG4gKiBAcGFyYW0gdiB2YWx1ZSBpbiBhcnJheVxuICogQHBhcmFtIGkgaW5kZXggb2YgdmFsdWUgaW4gYXJyYXlcbiAqIEBwYXJhbSB4IGFycmF5IGNvbnRhaW5pbmcgdGhlIHZhbHVlXG4gKiBAcmV0dXJucyByZWR1Y2VkIHZhbHVlXG4gKi9cbmV4cG9ydCB0eXBlIFJlZHVjZUZ1bmN0aW9uPFQsIFU+ID0gKGFjYzogVSwgdjogVCwgaTogbnVtYmVyLCB4OiBUW10gfCBudWxsKSA9PiBVO1xuXG5cbi8qKlxuICogSGFuZGxlIGVuZGluZyBvZiBhIGNvbWJpbmVkIGFycmF5LlxuICogQHBhcmFtIGRvbmVzIGnhtZfKsCBhcnJheSBkb25lP1xuICogQHJldHVybnMgY29tYmluZWQgYXJyYXkgZG9uZT9cbiAqL1xuZXhwb3J0IHR5cGUgRW5kRnVuY3Rpb24gPSAoZG9uZXM6IGJvb2xlYW5bXSkgPT4gYm9vbGVhbjtcblxuXG4vKipcbiAqIEhhbmRsZSBzd2FwcGluZyBvZiB0d28gdmFsdWVzIGluIGFuIGFycmF5LlxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYW4gaW5kZXhcbiAqIEBwYXJhbSBqIGFub3RoZXIgaW5kZXhcbiAqIEByZXR1cm5zIHggfCB4W2ldIOKHlCB4W2pdXG4gKi9cbmV4cG9ydCB0eXBlIFN3YXBGdW5jdGlvbjxUPiA9ICh4OiBUW10sIGk6IG51bWJlciwgajogbnVtYmVyKSA9PiBUW107XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gTUVUSE9EU1xuLy8gPT09PT09PT09PT09PT09XG5cbi8vICNyZWdpb24gSEVMUEVSU1xuLy8gLS0tLS0tLS0tLS0tLS0tXG5cbi8qKiBSZXR1cm4gdGhlIHNhbWUgKGZpcnN0KSB2YWx1ZS4gKi9cbmZ1bmN0aW9uIElERU5USVRZPFQ+KHY6IFQpOiBUIHtcbiAgcmV0dXJuIHY7XG59XG5cblxuLyoqIENvbXBhcmUgdHdvIHZhbHVlcy4gKi9cbmZ1bmN0aW9uIENPTVBBUkU8VD4oYTogVCwgYjogVCk6IG51bWJlciB7XG4gIHJldHVybiBhPGI/IC0xIDogKGE+Yj8gMSA6IDApO1xufVxuXG5cbi8qKiBGaW5kIHRoZSByZW1haW5kZXIgb2YgeC95IHdpdGggc2lnbiBvZiB5IChmbG9vcmVkIGRpdmlzaW9uKS4gKi9cbmZ1bmN0aW9uIG1vZCh4OiBudW1iZXIsIHk6IG51bWJlcik6IG51bWJlciB7XG4gIHJldHVybiB4IC0geSAqIE1hdGguZmxvb3IoeC95KTtcbn1cblxuXG4vKiogQ29udmVydCBhbiBpdGVyYWJsZSB0byBzZXQuICovXG5mdW5jdGlvbiB0b1NldDxULCBVPVQ+KHg6IFRbXSwgZm06IE1hcEZ1bmN0aW9uPFQsIFU+IHwgbnVsbD1udWxsKTogU2V0PFR8VT4ge1xuICBpZiAoIWZtKSByZXR1cm4gbmV3IFNldCh4KTtcbiAgY29uc3QgYSA9IG5ldyBTZXQ8VT4oKTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgYS5hZGQoZm0odiwgKytpLCB4KSk7XG4gIHJldHVybiBhO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIEdFTkVSQVRFXG4vLyAtLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogR2VuZXJhdGUgYXJyYXkgZnJvbSBnaXZlbiBudW1iZXIgcmFuZ2UuXG4gKiBAcGFyYW0gdiBzdGFydCBudW1iZXJcbiAqIEBwYXJhbSBWIGVuZCBudW1iZXIsIGV4Y2x1ZGluZ1xuICogQHBhcmFtIGR2IHN0ZXAgc2l6ZSBbMV1cbiAqIEByZXR1cm5zIFt2LCB2K2R2LCB2KzJkdiwgLi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZnJvbVJhbmdlKHY6IG51bWJlciwgVjogbnVtYmVyLCBkdjogbnVtYmVyPTEpOiBudW1iZXJbXSB7XG4gIGNvbnN0IG4gPSAoViAtIHYpL2R2LCBhID0gW107XG4gIGZvciAobGV0IGk9MDsgaTxuOyArK2ksIHYrPWR2KVxuICAgIGEucHVzaCh2KTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBHZW5lcmF0ZSBhcnJheSBmcm9tIHJlcGVhdGVkIGZ1bmN0aW9uIGludm9jYXRpb24uXG4gKiBAcGFyYW0gZm4gZnVuY3Rpb25cbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXNcbiAqIEByZXR1cm5zIFtmbigpLCBmbigpLCAuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmcm9tSW52b2NhdGlvbjxUPihmbjogKCkgPT4gVCwgbjogbnVtYmVyKTogVFtdIHtcbiAgY29uc3QgYSA9IFtdO1xuICBmb3IgKGxldCBpPTA7IGk8bjsgKytpKVxuICAgIGEucHVzaChmbigpKTtcbiAgcmV0dXJuIGE7XG59XG5leHBvcnQge2Zyb21JbnZvY2F0aW9uIGFzIGZyb21DYWxsfTtcblxuXG4vKipcbiAqIEdlbmVyYXRlIGFycmF5IGZyb20gcmVwZWF0ZWQgZnVuY3Rpb24gYXBwbGljYXRpb24uXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpKVxuICogQHBhcmFtIHYgc3RhcnQgdmFsdWVcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXNcbiAqIEByZXR1cm5zIFt2LCBmbSh2KSwgZm0oZm0odikpLCAuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmcm9tQXBwbGljYXRpb248VD4oZm06IE1hcEZ1bmN0aW9uPFQsIFQ+LCB2OiBULCBuOiBudW1iZXIpOiBUW10ge1xuICBjb25zdCBhID0gW107XG4gIGlmIChuIT09MCkgYS5wdXNoKHYpO1xuICBmb3IgKGxldCBpPTE7IGkhPT1uOyArK2kpXG4gICAgYS5wdXNoKHYgPSBmbSh2LCBpLCBudWxsKSk7XG4gIHJldHVybiBhO1xufVxuZXhwb3J0IHtmcm9tQXBwbGljYXRpb24gYXMgZnJvbUFwcGx5fTtcblxuXG4vKipcbiAqIENvbnZlcnQgYW4gaXRlcmFibGUgdG8gYXJyYXkuXG4gKiBAcGFyYW0geCBhbiBpdGVyYWJsZVxuICogQHJldHVybnMgeCBhcyBhcnJheVxuICovXG5leHBvcnQgZnVuY3Rpb24gZnJvbUl0ZXJhYmxlPFQ+KHg6IEl0ZXJhYmxlPFQ+KTogVFtdIHtcbiAgcmV0dXJuIFsuLi54XTtcbn1cbmV4cG9ydCB7ZnJvbUl0ZXJhYmxlIGFzIGZyb219O1xuXG5cbi8qKlxuICogQ29udmVydCBhbiBpdGVyYWJsZSB0byBhcnJheSFcbiAqIEBwYXJhbSB4IGFuIGl0ZXJhYmxlICh1cGRhdGFibGUgaWYgYXJyYXkhKVxuICogQHJldHVybnMgeCBhcyBhcnJheVxuICovXG5leHBvcnQgZnVuY3Rpb24gZnJvbUl0ZXJhYmxlJDxUPih4OiBJdGVyYWJsZTxUPik6IFRbXSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHgpPyB4IDogWy4uLnhdO1xufVxuZXhwb3J0IHtmcm9tSXRlcmFibGUkIGFzIGZyb20kfTtcbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBDTE9ORVxuLy8gLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIFNoYWxsb3cgY2xvbmUgYW4gYXJyYXkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHJldHVybnMgc2hhbGxvdyBjbG9uZSBvZiB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaGFsbG93Q2xvbmU8VD4oeDogVFtdKTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2UoKTtcbn1cbmV4cG9ydCB7c2hhbGxvd0Nsb25lIGFzIGNsb25lfTtcblxuXG4vKipcbiAqIERlZXAgY2xvbmUgYW4gYXJyYXkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHJldHVybnMgZGVlcCBjbG9uZSBvZiB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZWVwQ2xvbmU8VD4oeDogVFtdKTogVFtdIHtcbiAgcmV0dXJuIHN0cnVjdHVyZWRDbG9uZSh4KTtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBBQk9VVFxuLy8gLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIENoZWNrIGlmIHZhbHVlIGlzIGFuIGFycmF5LlxuICogQHBhcmFtIHYgYSB2YWx1ZVxuICogQHJldHVybnMgdiBpcyBhbiBhcnJheT9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzKHY6IHVua25vd24pOiB2IGlzIHVua25vd25bXSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHYpO1xufVxuXG5cbi8qKlxuICogT2J0YWluIGFsbCBpbmRpY2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEByZXR1cm5zIFswLCAxLCAuLi4sIHx4fC0xXVxuICovXG5leHBvcnQgZnVuY3Rpb24ga2V5czxUPih4OiBUW10pOiBudW1iZXJbXSB7XG4gIHJldHVybiBbLi4ueC5rZXlzKCldO1xufVxuXG5cbi8qKlxuICogTGlzdCBhbGwgaW5kaWNlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcmV0dXJucyAwLCAxLCAuLi4sIHx4fC0xXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpa2V5czxUPih4OiBUW10pOiBJdGVyYWJsZUl0ZXJhdG9yPG51bWJlcj4ge1xuICByZXR1cm4geC5rZXlzKCk7XG59XG5cblxuLyoqXG4gKiBHZXQgYWxsIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcmV0dXJucyBbduKCgCwgduKCgSwgLi4uXSB8IHbhtaIgPSB4W2ldXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWx1ZXM8VD4oeDogVFtdKTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2UoKTtcbn1cblxuXG4vKipcbiAqIExpc3QgYWxsIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcmV0dXJucyB24oKALCB24oKBLCAuLi4gfCB24bWiID0geFtpXVxuICovXG5leHBvcnQgZnVuY3Rpb24gaXZhbHVlczxUPih4OiBUW10pOiBJdGVyYWJsZUl0ZXJhdG9yPFQ+IHtcbiAgcmV0dXJuIHgudmFsdWVzKCk7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gYWxsIGluZGV4LXZhbHVlIHBhaXJzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEByZXR1cm5zIFtbMCwgduKCgF0sIFsxLCB24oKBXSwgLi4uXSB8IHbhtaIgPSB4W2ldXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbnRyaWVzPFQ+KHg6IFRbXSk6IEVudHJpZXM8VD4ge1xuICByZXR1cm4gWy4uLnguZW50cmllcygpXTtcbn1cblxuXG4vKipcbiAqIExpc3QgYWxsIGluZGV4LXZhbHVlIHBhaXJzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEByZXR1cm5zIFswLCB24oKAXSwgWzEsIHbigoFdLCAuLi4gfCB24bWiID0geFtpXVxuICovXG5leHBvcnQgZnVuY3Rpb24gaWVudHJpZXM8VD4oeDogVFtdKTogSUVudHJpZXM8VD4ge1xuICByZXR1cm4geC5lbnRyaWVzKCk7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gSU5ERVhcbi8vIC0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBHZXQgemVyby1iYXNlZCBpbmRleCBmb3IgYW4gZWxlbWVudCBpbiBhcnJheS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSDCsWluZGV4XG4gKiBAcmV0dXJucyBpJyB8IHhbaSddID0geFtpXTsgaScg4oiIIFswLCB8eHxdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmRleDxUPih4OiBUW10sIGk6IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgcmV0dXJuIGk+PTA/IE1hdGgubWluKGksIFgpIDogTWF0aC5tYXgoWCtpLCAwKTtcbn1cblxuXG4vKipcbiAqIEdldCB6ZXJvLWJhc2VkIGluZGV4IHJhbmdlIGZvciBwYXJ0IG9mIGFycmF5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpIGJlZ2luIMKxaW5kZXggWzBdXG4gKiBAcGFyYW0gSSBlbmQgwrFpbmRleCAoZXhjbHVzaXZlKSBbfHh8XVxuICogQHJldHVybnMgW2knLCBJJ10gfCBpJyDiiaQgSSc7IGknLCBJJyDiiIggWzAsIHx4fF1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluZGV4UmFuZ2U8VD4oeDogVFtdLCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPXgubGVuZ3RoKTogW251bWJlciwgbnVtYmVyXSB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaSA9IGk+PTA/IE1hdGgubWluKGksIFgpIDogTWF0aC5tYXgoWCtpLCAwKTtcbiAgSSA9IEk+PTA/IE1hdGgubWluKEksIFgpIDogTWF0aC5tYXgoWCtJLCAwKTtcbiAgcmV0dXJuIFtpLCBNYXRoLm1heChpLCBJKV07XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gTEVOR1RIXG4vLyAtLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIENoZWNrIGlmIGFuIGFycmF5IGlzIGVtcHR5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEByZXR1cm5zIHx4fCA9IDA/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0VtcHR5PFQ+KHg6IFRbXSk6IGJvb2xlYW4ge1xuICByZXR1cm4geC5sZW5ndGg9PT0wO1xufVxuXG5cbi8qKlxuICogRmluZCB0aGUgbGVuZ3RoIG9mIGFuIGFycmF5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpIGJlZ2luIMKxaW5kZXggWzBdXG4gKiBAcGFyYW0gSSBlbmQgwrFpbmRleCAoZXhjbHVzaXZlKSBbWF1cbiAqIEByZXR1cm5zIHx4W2kuLkldfFxuICovXG5leHBvcnQgZnVuY3Rpb24gbGVuZ3RoPFQ+KHg6IFRbXSwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj14Lmxlbmd0aCk6IG51bWJlciB7XG4gIFtpLCBJXSA9IGluZGV4UmFuZ2UoeCwgaSwgSSk7XG4gIHJldHVybiBJLWk7XG59XG5leHBvcnQge2xlbmd0aCBhcyBzaXplfTtcblxuXG4vKipcbiAqIFJlc2l6ZSBhbiBhcnJheSB0byBnaXZlbiBsZW5ndGghXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbmV3IGxlbmd0aFxuICogQHBhcmFtIHZkIGRlZmF1bHQgdmFsdWVcbiAqIEByZXR1cm5zIHJlc2l6ZWQgeFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzaXplJDxUPih4OiBUW10sIG46IG51bWJlciwgdmQ6IFQpOiBUW10ge1xuICBjb25zdCBYID0geC5sZW5ndGg7IHgubGVuZ3RoID0gbjtcbiAgaWYgKG4+WCkgeC5maWxsKHZkLCBYKTtcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBSZW1vdmUgYWxsIGVsZW1lbnRzIGZyb20gYW4gYXJyYXkhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcmV0dXJucyBjbGVhcmVkIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyJDxUPih4OiBUW10pOiBUW10ge1xuICB4Lmxlbmd0aCA9IDA7XG4gIHJldHVybiB4O1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIEdFVC9TRVRcbi8vIC0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEdldCB2YWx1ZSBhdCBpbmRleC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBpbmRleFxuICogQHJldHVybnMgeFtpXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0PFQ+KHg6IFRbXSwgaTogbnVtYmVyKTogVCB7XG4gIHJldHVybiB4W2luZGV4KHgsIGkpXTtcbn1cbmV4cG9ydCB7Z2V0IGFzIGF0fTtcblxuXG4vLyBHZXQgdmFsdWVzIGF0IGluZGV4IHJhbmdlLlxuLy8gZXhwb3J0IHtzbGljZSBhcyBnZXRSYW5nZX07XG5cblxuLyoqXG4gKiBHZXQgdmFsdWVzIGF0IGluZGljZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGlzIGluZGljZXNcbiAqIEByZXR1cm5zIFt4W2nigoBdLCB4W2nigoFdLCAuLi5dIHwgW2nigoAsIGnigoEsIC4uLl0gPSBpc1xuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QWxsPFQ+KHg6IFRbXSwgaXM6IG51bWJlcltdKTogVFtdIHtcbiAgcmV0dXJuIGlzLm1hcChpID0+IGdldCh4LCBpKSk7XG59XG5cblxuLyoqXG4gKiBHZXQgdmFsdWUgYXQgcGF0aCBpbiBhIG5lc3RlZCBhcnJheS5cbiAqIEBwYXJhbSB4IGEgbmVzdGVkIGFycmF5XG4gKiBAcGFyYW0gcCBwYXRoXG4gKiBAcmV0dXJucyB4W2nigoBdW2nigoFdWy4uLl0gfCBbaeKCgCwgaeKCgSwgLi4uXSA9IHBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFBhdGgoeDogdW5rbm93bltdLCBwOiBudW1iZXJbXSk6IHVua25vd24ge1xuICBsZXQgYTogdW5rbm93biB8IHVuZGVmaW5lZCA9IHg7XG4gIGZvciAoY29uc3QgaSBvZiBwKVxuICAgIGEgPSBpcyhhKT8gZ2V0KGEsIGkpIDogdW5kZWZpbmVkO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIENoZWNrIGlmIG5lc3RlZCBhcnJheSBoYXMgYSBwYXRoLlxuICogQHBhcmFtIHggYSBuZXN0ZWQgYXJyYXlcbiAqIEBwYXJhbSBwIHBhdGhcbiAqIEByZXR1cm5zIHhbaeKCgF1baeKCgV1bLi4uXSBleGlzdHM/IHwgW2nigoAsIGnigoEsIC4uLl0gPSBwXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNQYXRoKHg6IHVua25vd25bXSwgcDogbnVtYmVyW10pOiBib29sZWFuIHtcbiAgbGV0IGE6IHVua25vd24gfCB1bmRlZmluZWQgPSB4O1xuICBmb3IgKGNvbnN0IGkgb2YgcCkge1xuICAgIGlmICghaXMoYSkpIHJldHVybiBmYWxzZTtcbiAgICBhID0gZ2V0KGEsIGkpO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5cbi8qKlxuICogU2V0IHZhbHVlIGF0IGluZGV4LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpIGluZGV4XG4gKiBAcGFyYW0gdiB2YWx1ZVxuICogQHJldHVybnMgeCcgfCB4JyA9IHg7IHgnW2ldID0gdlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0PFQ+KHg6IFRbXSwgaTogbnVtYmVyLCB2OiBUKTogVFtdIHtcbiAgcmV0dXJuIHNldCQoeC5zbGljZSgpLCBpLCB2KTtcbn1cbmV4cG9ydCB7c2V0IGFzIHdpdGh9O1xuXG5cbi8qKlxuICogU2V0IHZhbHVlIGF0IGluZGV4IVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgaW5kZXhcbiAqIEBwYXJhbSB2IHZhbHVlXG4gKiBAcmV0dXJucyB4IHwgeFtpXSA9IHZcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldCQ8VD4oeDogVFtdLCBpOiBudW1iZXIsIHY6IFQpOiBUW10ge1xuICB4W2luZGV4KHgsIGkpXSA9IHY7XG4gIHJldHVybiB4O1xufVxuXG5cbi8vIFRPRE86IHNldFJhbmdlJCgpXG4vLyBUT0RPOiBzZXRBbGwkKClcblxuXG4vKipcbiAqIFNldCB2YWx1ZSBhdCBwYXRoIGluIGEgbmVzdGVkIGFycmF5IVxuICogQHBhcmFtIHggYSBuZXN0ZWQgYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIHAgcGF0aFxuICogQHBhcmFtIHYgdmFsdWVcbiAqIEByZXR1cm5zIHggfCB4W2nigoBdW2nigoFdWy4uLl0gPSB2OyBbaeKCgCwgaeKCgSwgLi4uXSA9IHBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFBhdGgkKHg6IHVua25vd25bXSwgcDogbnVtYmVyW10sIHY6IHVua25vd24pOiB1bmtub3duW10ge1xuICBjb25zdCB5ID0gZ2V0UGF0aCh4LCBwLnNsaWNlKDAsIC0xKSk7XG4gIGlmIChpcyh5KSkgc2V0JCh5LCBsYXN0KHApIGFzIG51bWJlciwgdik7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogRXhjaGFuZ2UgdHdvIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBhbiBpbmRleFxuICogQHBhcmFtIGogYW5vdGhlciBpbmRleFxuICogQHJldHVybnMgeCcgfCB4JyA9IHg7IHgnW2ldID0geFtqXTsgeCdbal0gPSB4W2ldXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzd2FwPFQ+KHg6IFRbXSwgaTogbnVtYmVyLCBqOiBudW1iZXIpOiBUW10ge1xuICByZXR1cm4gc3dhcCQoeC5zbGljZSgpLCBpLCBqKTtcbn1cblxuXG4vKipcbiAqIEV4Y2hhbmdlIHR3byB2YWx1ZXMhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gaSBhbiBpbmRleFxuICogQHBhcmFtIGogYW5vdGhlciBpbmRleFxuICogQHJldHVybnMgeCB8IHhbaV0g4oeUIHhbal1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN3YXAkPFQ+KHg6IFRbXSwgaTogbnVtYmVyLCBqOiBudW1iZXIpOiBUW10ge1xuICBpID0gaW5kZXgoeCwgaSk7IGogPSBpbmRleCh4LCBqKTtcbiAgY29uc3QgdCA9IHhbaV07IHhbaV0gPSB4W2pdOyB4W2pdID0gdDtcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBFeGNoYW5nZSB0d28gdmFsdWVzIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYW4gK3ZlIGluZGV4XG4gKiBAcGFyYW0gaiBhbm90aGVyICt2ZSBpbmRleFxuICogQHJldHVybnMgeCB8IHhbaV0g4oeUIHhbal1cbiAqL1xuZnVuY3Rpb24gc3dhcFJhdyQ8VD4oeDogVFtdLCBpOiBudW1iZXIsIGo6IG51bWJlcik6IFRbXSB7XG4gIGNvbnN0IHQgPSB4W2ldOyB4W2ldID0geFtqXTsgeFtqXSA9IHQ7XG4gIHJldHVybiB4O1xufVxuLy8gTk9URTogTWF5IGFsc28gYmUgY2FsbGVkIHN3YXBVbmNoZWNrZWQkKCkuXG5cblxuLyoqXG4gKiBFeGNoYW5nZSB0d28gcmFuZ2VzIG9mIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleCBvZiBmaXJzdCByYW5nZVxuICogQHBhcmFtIEkgZW5kIGluZGV4IG9mIGZpcnN0IHJhbmdlIChleGNsdXNpdmUpXG4gKiBAcGFyYW0gaiBiZWdpbiBpbmRleCBvZiBzZWNvbmQgcmFuZ2VcbiAqIEBwYXJhbSBKIGVuZCBpbmRleCBvZiBzZWNvbmQgcmFuZ2UgKGV4Y2x1c2l2ZSlcbiAqIEByZXR1cm5zIHgnIHwgeCcgPSB4OyB4J1tpLi5JXSA9IHhbai4uSl07IHgnW2ouLkpdID0geFtpLi5JXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3dhcFJhbmdlczxUPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBqOiBudW1iZXIsIEo6IG51bWJlcik6IFRbXSB7XG4gIFtpLCBJXSA9IGluZGV4UmFuZ2UoeCwgaSwgSSk7XG4gIFtqLCBKXSA9IGluZGV4UmFuZ2UoeCwgaiwgSik7XG4gIGlmIChqPGkpIFtpLCBJLCBqLCBKXSA9IFtqLCBKLCBpLCBJXTtcbiAgaWYgKGo8SSkgcmV0dXJuIHguc2xpY2UoKTsgIC8vIFNraXAgaWYgcmFuZ2VzIG92ZXJsYXAhXG4gIHJldHVybiB4LnNsaWNlKDAsIGkpLmNvbmNhdCh4LnNsaWNlKGosIEopLCB4LnNsaWNlKGksIGopLCB4LnNsaWNlKEkpKTtcbn1cblxuXG4vKipcbiAqIEV4Y2hhbmdlIHR3byByYW5nZXMgb2YgdmFsdWVzIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXggb2YgZmlyc3QgcmFuZ2VcbiAqIEBwYXJhbSBJIGVuZCBpbmRleCBvZiBmaXJzdCByYW5nZSAoZXhjbHVzaXZlKVxuICogQHBhcmFtIGogYmVnaW4gaW5kZXggb2Ygc2Vjb25kIHJhbmdlXG4gKiBAcGFyYW0gSiBlbmQgaW5kZXggb2Ygc2Vjb25kIHJhbmdlIChleGNsdXNpdmUpXG4gKiBAcmV0dXJucyB4IHwgeFtpLi5JXSDih5QgeFtqLi5KXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3dhcFJhbmdlcyQ8VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgajogbnVtYmVyLCBKOiBudW1iZXIpOiBUW10ge1xuICBbaSwgSV0gPSBpbmRleFJhbmdlKHgsIGksIEkpO1xuICBbaiwgSl0gPSBpbmRleFJhbmdlKHgsIGosIEopO1xuICBpZiAoajxpKSBbaSwgSSwgaiwgSl0gPSBbaiwgSiwgaSwgSV07XG4gIGlmIChqPEkpIHJldHVybiB4OyAgLy8gU2tpcCBpZiByYW5nZXMgb3ZlcmxhcCFcbiAgY29uc3QgdCA9IHguc2xpY2UoaSwgSSk7XG4gIHguc3BsaWNlKGksIEktaSwgLi4ueC5zbGljZShqLCBKKSk7XG4gIHguc3BsaWNlKGosIEotaiwgLi4udCk7XG4gIHJldHVybiB4O1xufVxuLy8gVE9ETzogc3dhcEFsbCQoKVxuXG5cbi8qKlxuICogUmVtb3ZlIHZhbHVlIGF0IGluZGV4LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpIGluZGV4XG4gKiBAcmV0dXJucyB4WzAuLmldIOKnuiB4W2krMS4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlPFQ+KHg6IFRbXSwgaTogbnVtYmVyKTogVFtdIHtcbiAgaSA9IGluZGV4KHgsIGkpO1xuICByZXR1cm4geC5zbGljZSgwLCBpKS5jb25jYXQoeC5zbGljZShpKzEpKTtcbn1cblxuXG4vKipcbiAqIFJlbW92ZSB2YWx1ZSBhdCBpbmRleCFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGluZGV4XG4gKiBAcmV0dXJucyB4IFxcXFw6IFtpXVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlJDxUPih4OiBUW10sIGk6IG51bWJlcik6IFRbXSB7XG4gIHguc3BsaWNlKGksIDEpO1xuICByZXR1cm4geDtcbn1cblxuXG4vKipcbiAqIFJlbW92ZSB2YWx1ZSBhdCBwYXRoIGluIGEgbmVzdGVkIGFycmF5IVxuICogQHBhcmFtIHggYSBuZXN0ZWQgYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIHAgcGF0aFxuICogQHJldHVybnMgeCBcXFxcOiBbaeKCgF1baeKCgV1bLi4uXSB8IFtp4oKALCBp4oKBLCAuLi5dID0gcFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVtb3ZlUGF0aCQoeDogdW5rbm93bltdLCBwOiBudW1iZXJbXSk6IHVua25vd25bXSB7XG4gIGNvbnN0IHkgPSBnZXRQYXRoKHgsIHAuc2xpY2UoMCwgLTEpKTtcbiAgaWYgKGlzKHkpKSB5LnNwbGljZShsYXN0KHApIGFzIG51bWJlciwgMSk7XG4gIHJldHVybiB4O1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIFNPUlRcbi8vIC0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEV4YW1pbmUgaWYgYXJyYXkgaXMgc29ydGVkLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHggaXMgc29ydGVkP1xuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTb3J0ZWQ8VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgcmV0dXJuIHNlYXJjaFVuc29ydGVkVmFsdWUoeCwgZmMsIGZtKSA9PT0gLTE7XG59XG5cblxuLyoqXG4gKiBFeGFtaW5lIGlmIGFycmF5IGhhcyBhbiB1bnNvcnRlZCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4IGlzIG5vdCBzb3J0ZWQ/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNVbnNvcnRlZFZhbHVlPFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIHJldHVybiBzZWFyY2hVbnNvcnRlZFZhbHVlKHgsIGZjLCBmbSkgPj0gMDtcbn1cblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgaW5kZXggb2YgYW4gdW5zb3J0ZWQgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgaW5kZXggb2YgZmlyc3QgdW5zb3J0ZWQgdmFsdWUsIC0xIGlmIHNvcnRlZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoVW5zb3J0ZWRWYWx1ZTxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlciB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgWCAgPSB4Lmxlbmd0aDtcbiAgaWYgKFg8PTEpIHJldHVybiAtMTtcbiAgbGV0IHcwID0gZm0oeFswXSwgMCwgeCk7XG4gIGZvciAobGV0IGk9MTsgaTxYOyArK2kpIHtcbiAgICBjb25zdCB3ID0gZm0oeFtpXSwgaSwgeCk7XG4gICAgaWYgKGZjKHcwLCB3KT4wKSByZXR1cm4gaTtcbiAgICB3MCA9IHc7XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuXG5cbi8qKlxuICogQXJyYW5nZSB2YWx1ZXMgaW4gb3JkZXIuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZzIHN3YXAgZnVuY3Rpb24gKHgsIGksIGopXG4gKiBAcmV0dXJucyB4JyB8IHgnID0geDsgeCdbaV0g4omkIHgnW2pdIOKIgCBpIOKJpCBqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzb3J0PFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsLCBmczogU3dhcEZ1bmN0aW9uPFQ+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgcmV0dXJuIHNvcnQkKHguc2xpY2UoKSwgZmMsIGZtLCBmcyk7XG59XG5leHBvcnQge3NvcnQgYXMgdG9Tb3J0ZWR9O1xuXG5cbi8qKlxuICogQXJyYW5nZSB2YWx1ZXMgaW4gb3JkZXIhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnMgc3dhcCBmdW5jdGlvbiAoeCwgaSwgailcbiAqIEByZXR1cm5zIHggfCB4W2ldIOKJpCB4W2pdIOKIgCBpIOKJpCBqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzb3J0JDxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCwgZnM6IFN3YXBGdW5jdGlvbjxUPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgaWYgKCFmbSAmJiAhZnMpIHJldHVybiB4LnNvcnQoZmMpO1xuICBjb25zdCBYICA9IHgubGVuZ3RoO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBmcyA9IGZzIHx8IHN3YXBSYXckO1xuICByZXR1cm4gcmFuZ2VkUGFydGlhbEludHJvU29ydCQoeCwgMCwgWCwgWCwgZmMsIGZtLCBmcyk7XG59XG5cblxuLyoqXG4gKiBBcnJhbmdlIGEgcmFuZ2Ugb2YgdmFsdWVzIGluIG9yZGVyLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4XG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggKGV4Y2x1c2l2ZSlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmcyBzd2FwIGZ1bmN0aW9uICh4LCBpLCBqKVxuICogQHJldHVybnMgeCcgfCB4JyA9IHg7IHgnW2ldIOKJpCB4J1tqXSDiiIAgaSDiiaQgalxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZ2VkU29ydDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwsIGZzOiBTd2FwRnVuY3Rpb248VD4gfCBudWxsPW51bGwpOiBUW10ge1xuICByZXR1cm4gcmFuZ2VkU29ydCQoeC5zbGljZSgpLCBpLCBJLCBmYywgZm0sIGZzKTtcbn1cblxuXG4vKipcbiAqIEFycmFuZ2UgYSByYW5nZSBvZiB2YWx1ZXMgaW4gb3JkZXIhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleFxuICogQHBhcmFtIEkgZW5kIGluZGV4IChleGNsdXNpdmUpXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnMgc3dhcCBmdW5jdGlvbiAoeCwgaSwgailcbiAqIEByZXR1cm5zIHggfCB4W2ldIOKJpCB4W2pdIOKIgCBpIOKJpCBqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5nZWRTb3J0JDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwsIGZzOiBTd2FwRnVuY3Rpb248VD4gfCBudWxsPW51bGwpOiBUW10ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGZzID0gZnMgfHwgc3dhcFJhdyQ7XG4gIFtpLCBJXSA9IGluZGV4UmFuZ2UoeCwgaSwgSSk7XG4gIHJldHVybiByYW5nZWRQYXJ0aWFsSW50cm9Tb3J0JCh4LCBpLCBJLCBJLWksIGZjLCBmbSwgZnMpO1xufVxuXG5cbi8qKlxuICogUGFydGlhbGx5IGFycmFuZ2UgdmFsdWVzIGluIG9yZGVyLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG1pbmltdW0gbnVtYmVyIG9mIHZhbHVlcyB0byBzb3J0XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnMgc3dhcCBmdW5jdGlvbiAoeCwgaSwgailcbiAqIEByZXR1cm5zIHgnIHwgeCcgPSB4OyB4J1tpXSDiiaQgeCdbal0g4oiAIGkg4omkIGpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnRpYWxTb3J0PFQsIFU9VD4oeDogVFtdLCBuOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwsIGZzOiBTd2FwRnVuY3Rpb248VD4gfCBudWxsPW51bGwpOiBUW10ge1xuICByZXR1cm4gcGFydGlhbFNvcnQkKHguc2xpY2UoKSwgbiwgZmMsIGZtLCBmcyk7XG59XG5cblxuLyoqXG4gKiBQYXJ0aWFsbHkgYXJyYW5nZSB2YWx1ZXMgaW4gb3JkZXIhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gbiBtaW5pbXVtIG51bWJlciBvZiB2YWx1ZXMgdG8gc29ydFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZzIHN3YXAgZnVuY3Rpb24gKHgsIGksIGopXG4gKiBAcmV0dXJucyB4IHwgeFtpXSDiiaQgeFtqXSDiiIAgaSDiiaQgalxuICovXG5leHBvcnQgZnVuY3Rpb24gcGFydGlhbFNvcnQkPFQsIFU9VD4oeDogVFtdLCBuOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwsIGZzOiBTd2FwRnVuY3Rpb248VD4gfCBudWxsPW51bGwpOiBUW10ge1xuICByZXR1cm4gcmFuZ2VkUGFydGlhbFNvcnQkKHgsIDAsIHgubGVuZ3RoLCBuLCBmYywgZm0sIGZzKTtcbn1cblxuXG4vKipcbiAqIFBhcnRpYWxseSBhcnJhbmdlIGEgcmFuZ2Ugb2YgdmFsdWVzIGluIG9yZGVyLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4XG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggKGV4Y2x1c2l2ZSlcbiAqIEBwYXJhbSBuIG1pbmltdW0gbnVtYmVyIG9mIHZhbHVlcyB0byBzb3J0XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnMgc3dhcCBmdW5jdGlvbiAoeCwgaSwgailcbiAqIEByZXR1cm5zIHgnIHwgeCcgPSB4OyB4J1tpXSDiiaQgeCdbal0g4oiAIGkg4omkIGpcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmdlZFBhcnRpYWxTb3J0PFQsIFU9VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsLCBmczogU3dhcEZ1bmN0aW9uPFQ+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgcmV0dXJuIHJhbmdlZFBhcnRpYWxTb3J0JCh4LnNsaWNlKCksIGksIEksIG4sIGZjLCBmbSwgZnMpO1xufVxuXG5cbi8qKlxuICogUGFydGlhbGx5IGFycmFuZ2UgYSByYW5nZSBvZiB2YWx1ZXMgaW4gb3JkZXIhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleFxuICogQHBhcmFtIEkgZW5kIGluZGV4IChleGNsdXNpdmUpXG4gKiBAcGFyYW0gbiBtaW5pbXVtIG51bWJlciBvZiB2YWx1ZXMgdG8gc29ydFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZzIHN3YXAgZnVuY3Rpb24gKHgsIGksIGopXG4gKiBAcmV0dXJucyB4IHwgeFtpXSDiiaQgeFtqXSDiiIAgaSDiiaQgalxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZ2VkUGFydGlhbFNvcnQkPFQsIFU9VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsLCBmczogU3dhcEZ1bmN0aW9uPFQ+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBmcyA9IGZzIHx8IHN3YXBSYXckO1xuICBbaSwgSV0gPSBpbmRleFJhbmdlKHgsIGksIEkpO1xuICByZXR1cm4gcmFuZ2VkUGFydGlhbEludHJvU29ydCQoeCwgaSwgSSwgbiwgZmMsIGZtLCBmcyk7XG59XG5cblxuLyoqXG4gKiBQYXJ0aWFsbHkgYXJyYW5nZSB2YWx1ZXMgaW4gb3JkZXIhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleFxuICogQHBhcmFtIEkgZW5kIGluZGV4IChleGNsdXNpdmUpXG4gKiBAcGFyYW0gbiBtaW5pbXVtIG51bWJlciBvZiB2YWx1ZXMgdG8gc29ydFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZzIHN3YXAgZnVuY3Rpb24gKHgsIGksIGopXG4gKiBAcmV0dXJucyB4IHwgeFtpXSDiiaQgeFtqXSDiiIAgaSDiiaQgalxuICovXG5mdW5jdGlvbiByYW5nZWRQYXJ0aWFsSW50cm9Tb3J0JDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IFRbXSB7XG4gIGNvbnN0IGQgPSBNYXRoLmZsb29yKE1hdGgubG9nMihJLWkpKjIpOyAgLy8gTWF4aW11bSBkZXB0aCBvZiByZWN1cnNpb25cbiAgY29uc3QgcyA9IDE2OyAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIHRvIHN3aXRjaCB0byBpbnNlcnRpb24gc29ydFxuICByZXR1cm4gcmFuZ2VkUGFydGlhbEludHJvU29ydERvJCh4LCBpLCBJLCBkLCBzLCBuLCBmYywgZm0sIGZzKTtcbn1cblxuXG4vLyBQYXJ0aWFsbHkgYXJyYW5nZSBhIHJhbmdlIG9mIHZhbHVlcyBpbiBvcmRlciB3aXRoIGh5YnJpZCBxdWljayBzb3J0LCBoZWFwIHNvcnQsIGFuZCBpbnNlcnRpb24gc29ydC5cbmZ1bmN0aW9uIHJhbmdlZFBhcnRpYWxJbnRyb1NvcnREbyQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBkOiBudW1iZXIsIHM6IG51bWJlciwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+LCBmczogU3dhcEZ1bmN0aW9uPFQ+KTogVFtdIHtcbiAgaWYgKG48PTAgfHwgSS1pPD0xKSByZXR1cm4geDsgICAgICAgICAgICAgICAgICAgICAvLyBOb3RoaW5nIHRvIHNvcnRcbiAgaWYgKEktaTw9cykgcmV0dXJuIHJhbmdlZFBhcnRpYWxJbnNlcnRpb25Tb3J0JCh4LCBpLCBJLCBuLCBmYywgZm0sIGZzKTsgIC8vIEluc2VydGlvbiBzb3J0XG4gIGlmIChkPD0wKSAgIHJldHVybiByYW5nZWRQYXJ0aWFsSGVhcFNvcnQkKHgsIGksIEksIG4sIGZjLCBmbSwgZnMpOyAgICAgICAvLyBIZWFwIHNvcnRcbiAgbGV0IHAgPSBpICsgTWF0aC5mbG9vcigoSS1pKSpNYXRoLnJhbmRvbSgpKTsgICAgICAgICAgICAvLyBDaG9vc2UgcGl2b3RcbiAgcCA9IHJhbmdlZFF1aWNrU29ydFBhcnRpdGlvbiQoeCwgaSwgSSwgcCwgZmMsIGZtLCBmcyk7ICAvLyBQYXJ0aXRpb24gYXJyYXlcbiAgcmFuZ2VkUGFydGlhbEludHJvU29ydERvJCh4LCBpLCAgIHAsIGQsIHMsIE1hdGgubWluKHAtaSwgbiksICAgZmMsIGZtLCBmcyk7ICAvLyBTb3J0IGxlZnQgcGFydFxuICByYW5nZWRQYXJ0aWFsSW50cm9Tb3J0RG8kKHgsIHArMSwgSSwgZCwgcywgTWF0aC5taW4oSS1wLTEsIG4pLCBmYywgZm0sIGZzKTsgIC8vIFNvcnQgcmlnaHQgcGFydFxuICByZXR1cm4geDtcbn1cblxuXG4vKipcbiAqIFBhcnRpYWxseSBhcnJhbmdlIGEgcmFuZ2Ugb2YgdmFsdWVzIGluIG9yZGVyIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXhcbiAqIEBwYXJhbSBJIGVuZCBpbmRleCAoZXhjbHVzaXZlKVxuICogQHBhcmFtIG4gbWluaW11bSBudW1iZXIgb2YgdmFsdWVzIHRvIHNvcnRcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmcyBzd2FwIGZ1bmN0aW9uICh4LCBpLCBqKVxuICogQHJldHVybnMgeCB8IHhbaV0g4omkIHhbal0g4oiAIGkg4omkIGpcbiAqL1xuZnVuY3Rpb24gX3JhbmdlZFBhcnRpYWxRdWlja1NvcnQkPFQsIFU9VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+LCBmczogU3dhcEZ1bmN0aW9uPFQ+KTogVFtdIHtcbiAgaWYgKG48PTAgfHwgSS1pPD0xKSByZXR1cm4geDsgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTm90aGluZyB0byBzb3J0XG4gIGxldCBwID0gaSArIE1hdGguZmxvb3IoKEktaSkqTWF0aC5yYW5kb20oKSk7ICAgICAgICAgICAgLy8gQ2hvb3NlIHBpdm90XG4gIHAgPSByYW5nZWRRdWlja1NvcnRQYXJ0aXRpb24kKHgsIGksIEksIHAsIGZjLCBmbSwgZnMpOyAgLy8gUGFydGl0aW9uIGFycmF5XG4gIF9yYW5nZWRQYXJ0aWFsUXVpY2tTb3J0JCh4LCBpLCAgIHAsIE1hdGgubWluKHAtaSwgbiksICAgZmMsIGZtLCBmcyk7ICAvLyBTb3J0IGxlZnQgcGFydFxuICBfcmFuZ2VkUGFydGlhbFF1aWNrU29ydCQoeCwgcCsxLCBJLCBNYXRoLm1pbihJLXAtMSwgbiksIGZjLCBmbSwgZnMpOyAgLy8gU29ydCByaWdodCBwYXJ0XG4gIHJldHVybiB4O1xufVxuXG5cbi8vIFRPRE86IE1ha2UgdGhpcyBhIGdlbmVyaWMgZnVuY3Rpb24uXG4vLyBQYXJ0aXRpb24gdGhlIGFycmF5IGludG8gdHdvIHBhcnRzLCBzdWNoIHRoYXQgdmFsdWVzIGluIHRoZSBmaXJzdCBwYXJ0IGFyZSBsZXNzIHRoYW4gdmFsdWVzIGluIHRoZSBzZWNvbmQgcGFydC5cbmZ1bmN0aW9uIHJhbmdlZFF1aWNrU29ydFBhcnRpdGlvbiQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBwOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4sIGZzOiBTd2FwRnVuY3Rpb248VD4pOiBudW1iZXIge1xuICBjb25zdCB3cCA9IGZtKHhbcF0sIHAsIHgpOyAgLy8gUGl2b3QgdmFsdWVcbiAgbGV0IGogID0gaS0xOyAgIC8vIExhc3QgaW5kZXggb2YgdmFsdWVzIOKJpCBwaXZvdFxuICBmcyh4LCBwLCBJLTEpOyAgLy8gTW92ZSBwaXZvdCB0byBlbmRcbiAgZm9yIChsZXQgaz1pOyBrPEktMTsgKytrKSB7XG4gICAgY29uc3Qgd2sgPSBmbSh4W2tdLCBrLCB4KTtcbiAgICBpZiAoZmMod2ssIHdwKSA+IDApIGNvbnRpbnVlO1xuICAgIGZzKHgsICsraiwgayk7ICAvLyBNb3ZlIHZhbHVlIOKJpCBwaXZvdCB0byBsZWZ0XG4gIH1cbiAgZnMoeCwgKytqLCBJLTEpOyAgLy8gTW92ZSBwaXZvdCB0byBtaWRkbGVcbiAgcmV0dXJuIGo7ICAvLyBSZXR1cm4gcGl2b3QgaW5kZXhcbn1cblxuXG4vKipcbiAqIFBhcnRpYWxseSBhcnJhbmdlIGEgcmFuZ2Ugb2YgdmFsdWVzIGluIG9yZGVyIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXhcbiAqIEBwYXJhbSBJIGVuZCBpbmRleCAoZXhjbHVzaXZlKVxuICogQHBhcmFtIG4gbWluaW11bSBudW1iZXIgb2YgdmFsdWVzIHRvIHNvcnRcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmcyBzd2FwIGZ1bmN0aW9uICh4LCBpLCBqKVxuICogQHJldHVybnMgeCB8IHhbaV0g4omkIHhbal0g4oiAIGkg4omkIGpcbiAqL1xuZnVuY3Rpb24gcmFuZ2VkUGFydGlhbEhlYXBTb3J0JDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IFRbXSB7XG4gIHJhbmdlZEJ1aWxkUmV2ZXJzZU1pbkhlYXAkKHgsIGksIEksIGZjLCBmbSwgZnMpO1xuICBmb3IgKGNvbnN0IHI9SS0xOyBuPjAgJiYgaTxJOyArK2ksIC0tbikge1xuICAgIGZzKHgsIGksIHIpOyAgLy8gTW92ZSByb290IHRvIHRoZSBiZWdpbm5pbmdcbiAgICByYW5nZWRSZXZlcnNlTWluSGVhcGlmeSQoeCwgaSsxLCBJLCByLCBmYywgZm0sIGZzKTsgIC8vIFJlYnVpbGQgaGVhcFxuICB9XG4gIHJldHVybiB4O1xufVxuXG5cbi8vIEJ1aWxkIGEgcmV2ZXJzZSBtaW4taGVhcCBmcm9tIGEgcmFuZ2Ugb2YgdmFsdWVzLCB3aGVyZSByb290IG5vZGUgaXMgdGhlIHNtYWxsZXN0IGFuZCBwbGFjZWQgYXQgdGhlIGVuZC5cbmZ1bmN0aW9uIHJhbmdlZEJ1aWxkUmV2ZXJzZU1pbkhlYXAkPFQsIFU9VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IHZvaWQge1xuICBmb3IgKGxldCByPUktTWF0aC5mbG9vcigoSS1pKS8yKTsgcjxJOyArK3IpICAvLyBSZXZlcnNlIG9mIHIgPSBYLzItMSAuLiAwXG4gICAgcmFuZ2VkUmV2ZXJzZU1pbkhlYXBpZnkkKHgsIGksIEksIHIsIGZjLCBmbSwgZnMpO1xufVxuXG5cbi8qKlxuICogUmV2ZXJzZSBtaW4taGVhcGlmeSBhIHJhbmdlIG9mIHZhbHVlcywgc3VjaCB0aGF0IHJvb3Qgbm9kZSBpcyB0aGUgc21hbGxlc3QgYW5kIHBsYWNlZCBhdCB0aGUgZW5kLlxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXhcbiAqIEBwYXJhbSBJIGVuZCBpbmRleCAoZXhjbHVzaXZlKVxuICogQHBhcmFtIHIgcm9vdCBpbmRleFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHBhcmFtIGZzIHN3YXAgZnVuY3Rpb24gKHgsIGksIGopXG4gKi9cbmZ1bmN0aW9uIHJhbmdlZFJldmVyc2VNaW5IZWFwaWZ5JDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIHI6IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IHZvaWQge1xuICBsZXQgcyAgPSByOyAgICAgICAgIC8vIEluZGV4IG9mIHNtYWxsZXN0IHZhbHVlXG4gIGNvbnN0IGx0ID0gMipyIC0gSTsgICAvLyBMZWZ0IGNoaWxkLCAgcmV2ZXJzZSBvZiBsdCA9IDIqcisxXG4gIGNvbnN0IHJ0ID0gbHQgIC0gMTsgICAvLyBSaWdodCBjaGlsZCwgcmV2ZXJzZSBvZiBydCA9IDIqcisyXG4gIGlmIChsdD49aSAmJiBmYyhmbSh4W2x0XSwgbHQsIHgpLCBmbSh4W3NdLCBzLCB4KSkgPCAwKSBzID0gbHQ7ICAvLyBMZWZ0IGNoaWxkIGlzIHNtYWxsZXI/XG4gIGlmIChydD49aSAmJiBmYyhmbSh4W3J0XSwgcnQsIHgpLCBmbSh4W3NdLCBzLCB4KSkgPCAwKSBzID0gcnQ7ICAvLyBSaWdodCBjaGlsZCBpcyBzbWFsbGVyP1xuICBpZiAocyAhPT0gcikgeyAgICAgLy8gU21hbGxlc3QgaXMgbm90IHJvb3Q/XG4gICAgZnMoeCwgcywgcik7ICAgICAvLyBTd2FwIHJvb3Qgd2l0aCBzbWFsbGVzdFxuICAgIHJhbmdlZFJldmVyc2VNaW5IZWFwaWZ5JCh4LCBpLCBJLCBzLCBmYywgZm0sIGZzKTsgIC8vIFJlYnVpbGQgaGVhcFxuICB9XG59XG5cblxuLy8gQnVpbGQgYSBtYXgtaGVhcCBmcm9tIGEgcmFuZ2Ugb2YgdmFsdWVzLCB3aGVyZSByb290IG5vZGUgaXMgdGhlIHNtYWxsZXN0IGFuZCBwbGFjZWQgYXQgdGhlIGJlZ2lubmluZy5cbmZ1bmN0aW9uIHJhbmdlZEJ1aWxkTWF4SGVhcCQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+LCBmczogU3dhcEZ1bmN0aW9uPFQ+KTogdm9pZCB7XG4gIGZvciAobGV0IHI9aStNYXRoLmZsb29yKChJLWkpLzIpLTE7IHI+PWk7IC0tcilcbiAgICByYW5nZWRNYXhIZWFwaWZ5JCh4LCBpLCBJLCByLCBmYywgZm0sIGZzKTtcbn1cblxuXG4vKipcbiAqIE1heC1oZWFwaWZ5IGEgcmFuZ2Ugb2YgdmFsdWVzLCBzdWNoIHRoYXQgcm9vdCBub2RlIGlzIHRoZSBsYXJnZXN0IGFuZCBwbGFjZWQgYXQgdGhlIGJlZ2lubmluZy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4XG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggKGV4Y2x1c2l2ZSlcbiAqIEBwYXJhbSByIHJvb3QgaW5kZXhcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmcyBzd2FwIGZ1bmN0aW9uICh4LCBpLCBqKVxuICovXG5mdW5jdGlvbiByYW5nZWRNYXhIZWFwaWZ5JDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIHI6IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IHZvaWQge1xuICBsZXQgcyAgPSByOyAgICAgICAgIC8vIEluZGV4IG9mIGxhcmdlc3QgdmFsdWVcbiAgY29uc3QgbHQgPSAyKnIgLSBpICsgMTsgIC8vIExlZnQgY2hpbGQsICBsaWtlIGx0ID0gMipyKzFcbiAgY29uc3QgcnQgPSBsdCAgKyAxOyAgICAgIC8vIFJpZ2h0IGNoaWxkLCBsaWtlIHJ0ID0gMipyKzJcbiAgaWYgKGx0PEkgJiYgZmMoZm0oeFtsdF0sIGx0LCB4KSwgZm0oeFtzXSwgcywgeCkpID4gMCkgcyA9IGx0OyAgLy8gTGVmdCBjaGlsZCAgaXMgbGFyZ2VyP1xuICBpZiAocnQ8SSAmJiBmYyhmbSh4W3J0XSwgcnQsIHgpLCBmbSh4W3NdLCBzLCB4KSkgPiAwKSBzID0gcnQ7ICAvLyBSaWdodCBjaGlsZCBpcyBsYXJnZXI/XG4gIGlmIChzICE9PSByKSB7ICAgICAvLyBMYXJnZXN0IGlzIG5vdCByb290P1xuICAgIGZzKHgsIHMsIHIpOyAgICAgLy8gU3dhcCByb290IHdpdGggbGFyZ2VzdFxuICAgIHJhbmdlZE1heEhlYXBpZnkkKHgsIGksIEksIHMsIGZjLCBmbSwgZnMpOyAgLy8gUmVidWlsZCBoZWFwXG4gIH1cbn1cblxuXG4vKipcbiAqIFBhcnRpYWxseSBhcnJhbmdlIGEgcmFuZ2Ugb2YgdmFsdWVzIGluIG9yZGVyIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXhcbiAqIEBwYXJhbSBJIGVuZCBpbmRleCAoZXhjbHVzaXZlKVxuICogQHBhcmFtIG4gbWluaW11bSBudW1iZXIgb2YgdmFsdWVzIHRvIHNvcnQgKGlnbm9yZWQpXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnMgc3dhcCBmdW5jdGlvbiAoeCwgaSwgailcbiAqIEByZXR1cm5zIHggfCB4W2ldIOKJpCB4W2pdIOKIgCBpIOKJpCBqXG4gKi9cbmZ1bmN0aW9uIHJhbmdlZFBhcnRpYWxJbnNlcnRpb25Tb3J0JDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IFRbXSB7XG4gIC8vIE5PVEU6IEluc2VydGlvbiBzb3J0IGRvZXMgbm90IHN1cHBvcnQgcGFydGlhbCBzb3J0aW5nLCBzbyB3ZSBpZ25vcmUgbi5cbiAgaWYgKGZzPT09c3dhcFJhdyQpIHJldHVybiByYW5nZWRQYXJ0aWFsSW5zZXJ0aW9uU29ydFN3YXBsZXNzJCh4LCBpLCBJLCBuLCBmYywgZm0sIGZzKTtcbiAgZWxzZSAgICAgICAgICAgICAgIHJldHVybiByYW5nZWRQYXJ0aWFsSW5zZXJ0aW9uU29ydFN3YXAkICAgICh4LCBpLCBJLCBuLCBmYywgZm0sIGZzKTtcbn1cblxuXG4vLyBTb3J0IGEgcmFuZ2Ugb2YgdmFsdWVzIGluIG9yZGVyIHdpdGggc3dhcC1lbmFibGVkIHZlcnNpb24gb2YgaW5zZXJ0aW9uIHNvcnQuXG5mdW5jdGlvbiByYW5nZWRQYXJ0aWFsSW5zZXJ0aW9uU29ydFN3YXAkPFQsIFU9VD4oeDogVFtdLCBpOiBudW1iZXIsIEk6IG51bWJlciwgX246IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IFRbXSB7XG4gIGZvciAobGV0IGo9aSsxOyBqPEk7ICsraikge1xuICAgIGNvbnN0IGtleSAgPSB4W2pdO1xuICAgIGNvbnN0IHdrZXkgPSBmbShrZXksIGosIHgpO1xuICAgIGZvciAobGV0IGs9ai0xOyBrPj1pICYmIGZjKGZtKHhba10sIGssIHgpLCB3a2V5KT4wOyAtLWspXG4gICAgICBmcyh4LCBrLCBrKzEpO1xuICB9XG4gIHJldHVybiB4O1xufVxuXG5cbi8vIFNvcnQgYSByYW5nZSBvZiB2YWx1ZXMgaW4gb3JkZXIgd2l0aCBzd2FwbGVzcyB2ZXJzaW9uIG9mIGluc2VydGlvbiBzb3J0LlxuZnVuY3Rpb24gcmFuZ2VkUGFydGlhbEluc2VydGlvblNvcnRTd2FwbGVzcyQ8VCwgVT1UPih4OiBUW10sIGk6IG51bWJlciwgSTogbnVtYmVyLCBfbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+LCBfZnM6IFN3YXBGdW5jdGlvbjxUPik6IFRbXSB7XG4gIGZvciAobGV0IGo9aSsxOyBqPEk7ICsraikge1xuICAgIGNvbnN0IGtleSAgPSB4W2pdO1xuICAgIGNvbnN0IHdrZXkgPSBmbShrZXksIGosIHgpO1xuICAgIGxldCBrID0gai0xO1xuICAgIGZvciAoOyBrPj1pICYmIGZjKGZtKHhba10sIGssIHgpLCB3a2V5KT4wOyAtLWspXG4gICAgICB4W2srMV0gPSB4W2tdO1xuICAgIHhbaysxXSA9IGtleTtcbiAgfVxuICByZXR1cm4geDtcbn1cblxuXG4vKipcbiAqIFBhcnRpYWxseSBhcnJhbmdlIGEgcmFuZ2Ugb2YgdmFsdWVzIGluIG9yZGVyIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXhcbiAqIEBwYXJhbSBJIGVuZCBpbmRleCAoZXhjbHVzaXZlKVxuICogQHBhcmFtIG4gbWluaW11bSBudW1iZXIgb2YgdmFsdWVzIHRvIHNvcnRcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmcyBzd2FwIGZ1bmN0aW9uICh4LCBpLCBqKVxuICogQHJldHVybnMgeCB8IHhbaV0g4omkIHhbal0g4oiAIGkg4omkIGpcbiAqL1xuZnVuY3Rpb24gX3JhbmdlZFBhcnRpYWxTZWxlY3Rpb25Tb3J0JDxULCBVPVQ+KHg6IFRbXSwgaTogbnVtYmVyLCBJOiBudW1iZXIsIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+LCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiwgZnM6IFN3YXBGdW5jdGlvbjxUPik6IFRbXSB7XG4gIGZvciAobGV0IGo9aTsgbj4wICYmIGo8STsgKytqLCAtLW4pIHtcbiAgICBsZXQgbCAgPSBqO1xuICAgIGxldCB3bCA9IGZtKHhbbF0sIGwsIHgpO1xuICAgIGZvciAobGV0IGs9aisxOyBrPEk7ICsraykge1xuICAgICAgY29uc3Qgd2sgPSBmbSh4W2tdLCBrLCB4KTtcbiAgICAgIGlmIChmYyh3bCwgd2spID4gMCkgeyBsID0gazsgd2wgPSB3azsgfVxuICAgIH1cbiAgICBmcyh4LCBqLCBsKTtcbiAgfVxuICByZXR1cm4geDtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBNSU5JTVVNL01BWElNVU1cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRmluZCBmaXJzdCBzbWFsbGVzdCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB2IHwgdiDiiaQgduG1ojsgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gbWluaW11bTxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFQge1xuICBjb25zdCBpID0gc2VhcmNoTWluaW11bVZhbHVlKHgsIGZjLCBmbSk7XG4gIHJldHVybiB4W2ldO1xufVxuZXhwb3J0IHttaW5pbXVtIGFzIG1pbn07XG5cblxuLyoqXG4gKiBGaW5kIGZpcnN0IHNtYWxsZXN0IGVudHJ5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIFttaW5faW5kZXgsIG1pbl92YWx1ZV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pbmltdW1FbnRyeTxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFtudW1iZXIsIFRdIHtcbiAgY29uc3QgaSA9IHNlYXJjaE1pbmltdW1WYWx1ZSh4LCBmYywgZm0pO1xuICByZXR1cm4gW2ksIHhbaV1dO1xufVxuZXhwb3J0IHttaW5pbXVtRW50cnkgYXMgbWluRW50cnl9O1xuXG5cbi8qKlxuICogRmluZCBmaXJzdCBsYXJnZXN0IHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHYgfCB2IOKJpSB24bWiOyB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXhpbXVtPFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVCB7XG4gIGNvbnN0IGkgPSBzZWFyY2hNYXhpbXVtVmFsdWUoeCwgZmMsIGZtKTtcbiAgcmV0dXJuIHhbaV07XG59XG5leHBvcnQge21heGltdW0gYXMgbWF4fTtcblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgbGFyZ2VzdCBlbnRyeS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbbWF4X2luZGV4LCBtYXhfdmFsdWVdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXhpbXVtRW50cnk8VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBbbnVtYmVyLCBUXSB7XG4gIGNvbnN0IGkgPSBzZWFyY2hNYXhpbXVtVmFsdWUoeCwgZmMsIGZtKTtcbiAgcmV0dXJuIFtpLCB4W2ldXTtcbn1cbmV4cG9ydCB7bWF4aW11bUVudHJ5IGFzIG1heEVudHJ5fTtcblxuXG4vKipcbiAqIEZpbmQgc21hbGxlc3QgYW5kIGxhcmdlc3QgdmFsdWVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIFttaW5fdmFsdWUsIG1heF92YWx1ZV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmdlPFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogW1QgfCB1bmRlZmluZWQsIFQgfCB1bmRlZmluZWRdIHtcbiAgY29uc3QgW2EsIGJdID0gcmFuZ2VFbnRyaWVzKHgsIGZjLCBmbSk7XG4gIHJldHVybiBbYVsxXSwgYlsxXV07XG59XG5cblxuLyoqXG4gKiBGaW5kIHNtYWxsZXN0IGFuZCBsYXJnZXN0IGVudHJpZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgW21pbl9lbnRyeSwgbWF4X2VudHJ5XVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZ2VFbnRyaWVzPFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogW1tudW1iZXIsIFQgfCB1bmRlZmluZWRdLCBbbnVtYmVyLCBUIHwgdW5kZWZpbmVkXV0ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IFggID0geC5sZW5ndGg7XG4gIGlmIChYPT09MCkgcmV0dXJuIFtbLTEsIHVuZGVmaW5lZF0sIFstMSwgdW5kZWZpbmVkXV07XG4gIGxldCB2ICA9IHhbMF0sIHcgPSBmbSh2LCAwLCB4KTtcbiAgbGV0IG1pID0gMCwgbXYgPSB2LCBtdyA9IHc7XG4gIGxldCBuaSA9IDAsIG52ID0gdiwgbncgPSB3O1xuICBmb3IgKGxldCBpPTE7IGk8WDsgKytpKSB7XG4gICAgdiA9IHhbaV07IHcgPSBmbSh2LCBpLCB4KTtcbiAgICBpZiAoZmModywgbXcpPDApIHsgbWkgPSBpOyBtdiA9IHY7IG13ID0gdzsgfVxuICAgIGlmIChmYyh3LCBudyk+MCkgeyBuaSA9IGk7IG52ID0gdjsgbncgPSB3OyB9XG4gIH1cbiAgcmV0dXJuIFtbbWksIG12XSwgW25pLCBudl1dO1xufVxuXG5cbi8qKlxuICogRmluZCBzbWFsbGVzdCB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlc1xuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgbiBzbWFsbGVzdCB2YWx1ZXMgaW4gYXNjZW5kaW5nIG9yZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtaW5pbXVtczxULCBVPVQ+KHg6IFRbXSwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPG51bWJlcnxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGNvbnN0IGlzID0gc2VhcmNoTWluaW11bVZhbHVlcyh4LCBuLCBmYywgZm0pO1xuICByZXR1cm4gaXMubWFwKGkgPT4geFtpXSk7XG59XG5cblxuLyoqXG4gKiBGaW5kIHNtYWxsZXN0IGVudHJpZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlc1xuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgbiBzbWFsbGVzdCBlbnRyaWVzIGluIGFzY2VuZGluZyBvcmRlclxuICovXG5leHBvcnQgZnVuY3Rpb24gbWluaW11bUVudHJpZXM8VCwgVT1UPih4OiBUW10sIG46IG51bWJlciwgZmM6IENvbXBhcmVGdW5jdGlvbjxudW1iZXJ8VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBbbnVtYmVyLCBUXVtdIHtcbiAgY29uc3QgaXMgPSBzZWFyY2hNaW5pbXVtVmFsdWVzKHgsIG4sIGZjLCBmbSk7XG4gIHJldHVybiBpcy5tYXAoaSA9PiBbaSwgeFtpXV0pO1xufVxuXG5cbi8qKlxuICogRmluZCBsYXJnZXN0IHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzXG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBuIGxhcmdlc3QgdmFsdWVzIGluIGRlc2NlbmRpbmcgb3JkZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1heGltdW1zPFQsIFU9VD4oeDogVFtdLCBuOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248bnVtYmVyfFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgY29uc3QgaXMgPSBzZWFyY2hNYXhpbXVtVmFsdWVzKHgsIG4sIGZjLCBmbSk7XG4gIHJldHVybiBpcy5tYXAoaSA9PiB4W2ldKTtcbn1cblxuXG4vKipcbiAqIEZpbmQgbGFyZ2VzdCBlbnRyaWVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXNcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIG4gbGFyZ2VzdCBlbnRyaWVzIGluIGRlc2NlbmRpbmcgb3JkZXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1heGltdW1FbnRyaWVzPFQsIFU9VD4oeDogVFtdLCBuOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248bnVtYmVyfFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogW251bWJlciwgVF1bXSB7XG4gIGNvbnN0IGlzID0gc2VhcmNoTWF4aW11bVZhbHVlcyh4LCBuLCBmYywgZm0pO1xuICByZXR1cm4gaXMubWFwKGkgPT4gW2ksIHhbaV1dKTtcbn1cblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgaW5kZXggb2YgbWluaW11bSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpbmRleCBvZiBtaW5pbXVtIHZhbHVlLCAtMSBpZiBlbXB0eVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoTWluaW11bVZhbHVlPFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBYICA9IHgubGVuZ3RoO1xuICBpZiAoWD09PTApIHJldHVybiAtMTtcbiAgbGV0IG1pID0gMCwgbXcgPSBmbSh4WzBdLCAwLCB4KTtcbiAgZm9yIChsZXQgaT0xOyBpPFg7ICsraSkge1xuICAgIGNvbnN0IHcgPSBmbSh4W2ldLCBpLCB4KTtcbiAgICBpZiAoZmModywgbXcpPDApIHsgbWkgPSBpOyBtdyA9IHc7IH1cbiAgfVxuICByZXR1cm4gbWk7XG59XG5cblxuLyoqXG4gKiBGaW5kIGZpcnN0IGluZGV4IG9mIG1heGltdW0gdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggb2YgbWF4aW11bSB2YWx1ZSwgLTEgaWYgZW1wdHlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaE1heGltdW1WYWx1ZTxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlciB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgWCAgPSB4Lmxlbmd0aDtcbiAgaWYgKFg9PT0wKSByZXR1cm4gLTE7XG4gIGxldCBuaSA9IDAsIG53ID0gZm0oeFswXSwgMCwgeCk7XG4gIGZvciAobGV0IGk9MTsgaTxYOyArK2kpIHtcbiAgICBjb25zdCB3ID0gZm0oeFtpXSwgaSwgeCk7XG4gICAgaWYgKGZjKHcsIG53KT4wKSB7IG5pID0gaTsgbncgPSB3OyB9XG4gIH1cbiAgcmV0dXJuIG5pO1xufVxuXG5cbi8qKlxuICogRmluZCBpbmRpY2VzIG9mIG1pbmltdW0gdmFsdWVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXNcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGluZGljZXMgb2YgbWluaW11bSB2YWx1ZXMgaW4gYXNjZW5kaW5nIG9yZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hNaW5pbXVtVmFsdWVzPFQsIFU9VD4oeDogVFtdLCBuOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248bnVtYmVyfFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyW10ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IFggID0geC5sZW5ndGg7XG4gIC8vIENyZWF0ZSBhIG1heCBoZWFwIG9mIGluZGljZXMuXG4gIGNvbnN0IElIID0gTWF0aC5taW4obiwgWCk7XG4gIGNvbnN0IGloID0gZnJvbVJhbmdlKDAsIElIKTtcbiAgcmFuZ2VkQnVpbGRNYXhIZWFwJChpaCwgMCwgSUgsIGZjLCBpID0+IGZtKHhbaV0sIGksIHgpLCBzd2FwUmF3JCk7XG4gIGxldCB3ciA9IGZtKHhbaWhbMF1dLCBpaFswXSwgeCk7XG4gIC8vIFNlYXJjaCBmb3IgbWluaW11bSB2YWx1ZXMsIGFuZCB1cGRhdGUgaGVhcC5cbiAgZm9yIChsZXQgaT1uOyBpPFg7ICsraSkge1xuICAgIGNvbnN0IHcgPSBmbSh4W2ldLCBpLCB4KTtcbiAgICBpZiAoZmModywgd3IpID49IDApIGNvbnRpbnVlO1xuICAgIGloWzBdID0gaTtcbiAgICByYW5nZWRNYXhIZWFwaWZ5JChpaCwgMCwgSUgsIDAsIGZjLCBpID0+IGZtKHhbaV0sIGksIHgpLCBzd2FwUmF3JCk7XG4gICAgd3IgPSBmbSh4W2loWzBdXSwgaWhbMF0sIHgpO1xuICB9XG4gIC8vIFNvcnQgbWF4IGhlYXAgaW4gYXNjZW5kaW5nIG9yZGVyLlxuICBpaC5zb3J0KChpLCBqKSA9PiBmYyhmbSh4W2ldLCBpLCB4KSwgZm0oeFtqXSwgaiwgeCkpKTtcbiAgcmV0dXJuIGloO1xufVxuXG5cbi8qKlxuICogRmluZCBpbmRpY2VzIG9mIG1heGltdW0gdmFsdWVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXNcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGluZGljZXMgb2YgbWF4aW11bSB2YWx1ZXMgaW4gZGVzY2VuZGluZyBvcmRlclxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoTWF4aW11bVZhbHVlczxULCBVPVQ+KHg6IFRbXSwgbjogbnVtYmVyLCBmYzogQ29tcGFyZUZ1bmN0aW9uPG51bWJlcnxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlcltdIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBjb25zdCBmZCA9IChhOiBudW1iZXJ8VHxVLCBiOiBudW1iZXJ8VHxVKSA9PiAtZmMoYSwgYik7XG4gIHJldHVybiBzZWFyY2hNaW5pbXVtVmFsdWVzKHgsIG4sIGZkLCBmbSk7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gQ09NUEFSRVxuLy8gLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRXhhbWluZSBpZiB0d28gYXJyYXlzIGFyZSBlcXVhbC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBhbm90aGVyIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4ID0geT9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRXF1YWw8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICBjb25zdCBYID0geC5sZW5ndGgsIFkgPSB5Lmxlbmd0aDtcbiAgcmV0dXJuIFg9PT1ZICYmIGNvbXBhcmUoeCwgeSwgZmMsIGZtKT09PTA7XG59XG5cblxuLyoqXG4gKiBDb21wYXJlIHR3byBhcnJheXMgKGxleGljb2dyYXBoaWNhbGx5KS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBhbm90aGVyIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4PHk6IC12ZSwgeD15OiAwLCB4Pnk6ICt2ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29tcGFyZTxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBYICA9IHgubGVuZ3RoO1xuICBjb25zdCBZICA9IHkubGVuZ3RoO1xuICBmb3IgKGxldCBpPTAsIEk9TWF0aC5taW4oWCwgWSk7IGk8STsgKytpKSB7XG4gICAgY29uc3Qgd3ggPSBmbSh4W2ldLCBpLCB4KTtcbiAgICBjb25zdCB3eSA9IGZtKHlbaV0sIGksIHkpO1xuICAgIGNvbnN0IGMgID0gZmMod3gsIHd5KTtcbiAgICBpZiAoYyE9PTApIHJldHVybiBjO1xuICB9XG4gIHJldHVybiBNYXRoLnNpZ24oWC1ZKTtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBQQVJUXG4vLyAtLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBHZXQgZmlyc3QgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHZkIGRlZmF1bHQgdmFsdWVcbiAqIEByZXR1cm5zIHhbMF0gfHwgdmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhlYWQ8VD4oeDogVFtdLCB2ZD86IFQpOiBUIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHgubGVuZ3RoPjA/IHhbMF0gOiB2ZDtcbn1cbmV4cG9ydCB7aGVhZCBhcyBmcm9udH07XG5leHBvcnQge2hlYWQgYXMgZmlyc3R9O1xuXG5cbi8qKlxuICogR2V0IHZhbHVlcyBleGNlcHQgZmlyc3QuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHJldHVybnMgeFsxLi58eHxdXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0YWlsPFQ+KHg6IFRbXSk6IFRbXSB7XG4gIHJldHVybiB4LnNsaWNlKDEpO1xufVxuXG5cbi8qKlxuICogR2V0IHZhbHVlcyBleGNlcHQgbGFzdC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcmV0dXJucyB4WzAuLnx4fC0xXVxuICovXG5leHBvcnQgZnVuY3Rpb24gaW5pdDxUPih4OiBUW10pOiBUW10ge1xuICByZXR1cm4geC5zbGljZSgwLCAtMSk7XG59XG5cblxuLyoqXG4gKiBHZXQgbGFzdCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gdmQgZGVmYXVsdCB2YWx1ZVxuICogQHJldHVybnMgeFt8eHwtMV0gfHwgdmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxhc3Q8VD4oeDogVFtdLCB2ZD86IFQpOiBUIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHgubGVuZ3RoPjA/IHhbeC5sZW5ndGgtMV0gOiB2ZDtcbn1cbmV4cG9ydCB7bGFzdCBhcyBiYWNrfTtcblxuXG4vKipcbiAqIEdldCB2YWx1ZXMgZnJvbSBtaWRkbGUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXhcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWzFdXG4gKiBAcmV0dXJucyB4W2kuLmkrbl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1pZGRsZTxUPih4OiBUW10sIGk6IG51bWJlciwgbjogbnVtYmVyPTEpOiBUW10ge1xuICBpID0gaW5kZXgoeCwgaSk7XG4gIG4gPSBNYXRoLm1heChuLCAwKTtcbiAgcmV0dXJuIHguc2xpY2UoaSwgaStuKTtcbn1cblxuXG4vKipcbiAqIEdldCBwYXJ0IG9mIGFuIGFycmF5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4IFswXVxuICogQHBhcmFtIEkgZW5kIGluZGV4IFt8eHxdXG4gKiBAcmV0dXJucyB4W2kuLkldXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzbGljZTxUPih4OiBUW10sIGk6IG51bWJlcj0wLCBJOiBudW1iZXI9eC5sZW5ndGgpOiBUW10ge1xuICByZXR1cm4geC5zbGljZShpLCBJKTtcbn1cblxuXG4vKipcbiAqIEdldCBwYXJ0IG9mIGFuIGFycmF5IVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXggWzBdXG4gKiBAcGFyYW0gSSBlbmQgaW5kZXggW3x4fF1cbiAqIEByZXR1cm5zIHggPSB4W2kuLkldXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzbGljZSQ8VD4oeDogVFtdLCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPXgubGVuZ3RoKTogVFtdIHtcbiAgeC5jb3B5V2l0aGluKDAsIGksIEkpO1xuICB4Lmxlbmd0aCA9IGxlbmd0aCh4LCBpLCBJKTtcbiAgcmV0dXJuIHg7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gU0VBUkNIIFZBTFVFXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIENoZWNrIGlmIGFycmF5IGhhcyBhIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB2IHNlYXJjaCB2YWx1ZVxuICogQHBhcmFtIGkgYmVnaW4gaW5kZXggWzBdXG4gKiBAcmV0dXJucyB2IOKIiCB4W2kuLl0/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmNsdWRlczxUPih4OiBUW10sIHY6IFQsIGk6IG51bWJlcj0wKTogYm9vbGVhbiB7XG4gIHJldHVybiB4LmluY2x1ZGVzKHYsIGkpO1xufVxuXG5cbi8qKlxuICogRXhhbWluZSBpZiBhcnJheSBoYXMgYSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gdiBzZWFyY2ggdmFsdWVcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHYg4oiIIHg/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNWYWx1ZTxULCBVPVQ+KHg6IFRbXSwgdjogVCwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICByZXR1cm4gc2VhcmNoVmFsdWUoeCwgdiwgZmMsIGZtKSA+PSAwO1xufVxuXG5cbi8qKlxuICogRmluZCBmaXJzdCBpbmRleCBvZiBhIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB2IHNlYXJjaCB2YWx1ZVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggb2YgdmFsdWUsIC0xIGlmIG5vdCBmb3VuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoVmFsdWU8VCwgVT1UPih4OiBUW10sIHY6IFQsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBudW1iZXIge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHcgID0gZm0odiwgMCwgbnVsbCk7IGxldCBpID0gLTE7XG4gIGZvciAoY29uc3Qgdnggb2YgeCkge1xuICAgIGNvbnN0IHd4ID0gZm0odngsICsraSwgeCk7XG4gICAgaWYgKGZjKHd4LCB3KT09PTApIHJldHVybiBpO1xuICB9XG4gIHJldHVybiAtMTtcbn1cblxuXG4vKipcbiAqIEZpbmQgbGFzdCBpbmRleCBvZiBhIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB2IHNlYXJjaCB2YWx1ZVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgbGFzdCBpbmRleCBvZiB2YWx1ZSwgLTEgaWYgbm90IGZvdW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hWYWx1ZVJpZ2h0PFQsIFU9VD4oeDogVFtdLCB2OiBULCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB3ID0gZm0odiwgMCwgbnVsbCk7XG4gIGZvciAobGV0IGk9eC5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgY29uc3Qgd3ggPSBmbSh4W2ldLCBpLCB4KTtcbiAgICBpZiAoZmMod3gsIHcpPT09MCkgcmV0dXJuIGk7XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuXG5cbi8qKlxuICogRmluZCBpbmRpY2VzIG9mIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB2IHNlYXJjaCB2YWx1ZVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgaW5kaWNlcyBvZiB2YWx1ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoVmFsdWVBbGw8VCwgVT1UPih4OiBUW10sIHY6IFQsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBudW1iZXJbXSB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgdyA9IGZtKHYsIDAsIG51bGwpO1xuICBsZXQgaSA9IC0xOyBjb25zdCBhID0gW107XG4gIGZvciAoY29uc3Qgdnggb2YgeCkge1xuICAgIGNvbnN0IHd4ID0gZm0odngsICsraSwgeCk7XG4gICAgaWYgKGZjKHd4LCB3KT09PTApIGEucHVzaChpKTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgaW5kZXggb2YgYW4gYWRqYWNlbnQgZHVwbGljYXRlIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGluZGV4IG9mIGZpcnN0IGFkamFjZW50IGR1cGxpY2F0ZSB2YWx1ZSwgLTEgaWYgbm9uZVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoQWRqYWNlbnREdXBsaWNhdGVWYWx1ZTxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IG51bWJlciB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgWCAgPSB4Lmxlbmd0aDtcbiAgaWYgKFg8PTEpIHJldHVybiAtMTtcbiAgbGV0IHcwID0gZm0oeFswXSwgMCwgeCk7XG4gIGZvciAobGV0IGk9MTsgaTxYOyArK2kpIHtcbiAgICBjb25zdCB3ID0gZm0oeFtpXSwgaSwgeCk7XG4gICAgaWYgKGZjKHcwLCB3KT09PTApIHJldHVybiBpO1xuICAgIHcwID0gdztcbiAgfVxuICByZXR1cm4gLTE7XG59XG5leHBvcnQge3NlYXJjaEFkamFjZW50RHVwbGljYXRlVmFsdWUgYXMgc2VhcmNoQWRqYWNlbnREdXBsaWNhdGV9O1xuXG5cbi8qKlxuICogRmluZCBmaXJzdCBpbmRleCB3aGVyZSB0d28gYXJyYXlzIGRpZmZlci5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBhbm90aGVyIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpbmRleCB3aGVyZSB4W2ldIOKJoCB5W2ldLCBvciAtMVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoTWlzbWF0Y2hlZFZhbHVlPFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBudW1iZXIge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgY29uc3QgWSA9IHkubGVuZ3RoO1xuICBjb25zdCBJID0gTWF0aC5taW4oWCwgWSk7XG4gIGZvciAobGV0IGk9MDsgaTxJOyArK2kpIHtcbiAgICBjb25zdCB3eCA9IGZtKHhbaV0sIGksIHgpO1xuICAgIGNvbnN0IHd5ID0gZm0oeVtpXSwgaSwgeSk7XG4gICAgaWYgKGZjKHd4LCB3eSkhPT0wKSByZXR1cm4gaTtcbiAgfVxuICByZXR1cm4gWD09PVk/IC0xIDogSTtcbn1cbmV4cG9ydCB7c2VhcmNoTWlzbWF0Y2hlZFZhbHVlIGFzIHNlYXJjaE1pc21hdGNofTtcbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBBUlJBTkdFTUVOVFNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRXhhbWluZSBpZiBhcnJheSBzdGFydHMgd2l0aCBhIHByZWZpeC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBzZWFyY2ggcHJlZml4XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4WzAuLnx5fF0gPSB5P1xuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzUHJlZml4PFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgY29uc3QgWSA9IHkubGVuZ3RoO1xuICByZXR1cm4gWT09PTAgfHwgY29tcGFyZSh4LnNsaWNlKDAsIFkpLCB5LCBmYywgZm0pPT09MDtcbn1cbmV4cG9ydCB7aGFzUHJlZml4IGFzIHN0YXJ0c1dpdGh9O1xuXG5cbi8qKlxuICogRXhhbWluZSBpZiBhcnJheSBlbmRzIHdpdGggYSBzdWZmaXguXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgc2VhcmNoIHN1ZmZpeFxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeFt8eHwtfHl8Li5dID0geT9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1N1ZmZpeDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGNvbnN0IFkgPSB5Lmxlbmd0aDtcbiAgcmV0dXJuIFk9PT0wIHx8IGNvbXBhcmUoeC5zbGljZSgtWSksIHksIGZjLCBmbSk9PT0wO1xufVxuZXhwb3J0IHtoYXNTdWZmaXggYXMgZW5kc1dpdGh9O1xuXG5cbi8qKlxuICogRXhhbWluZSBpZiBhcnJheSBjb250YWlucyBhbiBpbmZpeC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBzZWFyY2ggaW5maXhcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbaS4uSV0gPSB5IGZvciBzb21lIGksIEk/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNJbmZpeDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIHJldHVybiBzZWFyY2hJbmZpeCh4LCB5LCBmYywgZm0pID49IDA7XG59XG5cblxuLyoqXG4gKiBFeGFtaW5lIGlmIGFycmF5IGhhcyBhIHN1YnNlcXVlbmNlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB5IHNlYXJjaCBzdWJzZXF1ZW5jZVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeFtp4oKAXSDip7ogeFtp4oKBXSDip7ogLi4uID0geSwgZm9yIHNvbWUgaeKCgCwgaeKCgSwgLi4uPyB8IGnigoAgPCBp4oKBIDwgLi4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNTdWJzZXF1ZW5jZTxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIHJldHVybiBzZWFyY2hTdWJzZXF1ZW5jZSh4LCB5LCBmYywgZm0pID49IDA7XG59XG5cblxuLyoqXG4gKiBFeGFtaW5lIGlmIGFycmF5IGhhcyBhIHBlcm11dGF0aW9uLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB5IHNlYXJjaCBwZXJtdXRhdGlvblxuICogQHBhcmFtIGZjIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmbSBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHJldHVybnMgeCBjb250YWlucyBhIHNodWZmbGVkIHZlcnNpb24gb2YgeT9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1Blcm11dGF0aW9uPFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgY29uc3QgeDEgPSBmbT8geC5tYXAoZm0pIDogeC5zbGljZSgpO1xuICBjb25zdCB5MSA9IGZtPyB5Lm1hcChmbSkgOiB5LnNsaWNlKCk7XG4gIHJldHVybiBoYXNTdWJzZXF1ZW5jZTxUfFU+KHgxLnNvcnQoKSwgeTEuc29ydCgpLCBmYyk7XG4gIC8vIHJldHVybiBoYXNTdWJzZXF1ZW5jZTxUfFU+KHgxLnNvcnQoKSwgeTEuc29ydCgpLCBmYywgZm0pO1xufVxuXG5cbi8qKlxuICogT2J0YWluIGFsbCBwb3NzaWJsZSBwcmVmaXhlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHJldHVybnMgW1tdLCB4Wy4uMV0sIHhbLi4yXSwgLi4uXSBpZiBuPDA7IFt4Wy4ubl1dIG90aGVyd2lzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gcHJlZml4ZXM8VD4oeDogVFtdLCBuOiBudW1iZXI9LTEpOiBUW11bXSB7XG4gIHJldHVybiBbLi4uaXByZWZpeGVzKHgsIG4pXTtcbn1cblxuXG4vKipcbiAqIExpc3QgYWxsIHBvc3NpYmxlIHByZWZpeGVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWy0xIOKHkiBhbnldXG4gKiBAcmV0dXJucyBbXSwgeFsuLjFdLCB4Wy4uMl0sIC4uLiBpZiBuPDA7IHhbLi5uXSBvdGhlcndpc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uKiBpcHJlZml4ZXM8VD4oeDogVFtdLCBuOiBudW1iZXI9LTEpOiBJdGVyYWJsZUl0ZXJhdG9yPFRbXT4ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGlmIChuPlgpICByZXR1cm47XG4gIGlmIChuPj0wKSB7IHlpZWxkIHguc2xpY2UoMCwgbik7IHJldHVybjsgfVxuICBmb3IgKGxldCBpPTA7IGk8PVg7ICsraSlcbiAgICB5aWVsZCB4LnNsaWNlKDAsIGkpO1xufVxuXG5cbi8qKlxuICogT2J0YWluIGFsbCBwb3NzaWJsZSBzdWZmaXhlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHJldHVybnMgW3hbMC4uXSwgeFsxLi5dLCB4WzIuLl0sIC4uLl0gaWYgbjwwOyBbeFstbi4uXV0gb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdWZmaXhlczxUPih4OiBUW10sIG46IG51bWJlcj0tMSk6IFRbXVtdIHtcbiAgcmV0dXJuIFsuLi5pc3VmZml4ZXMoeCwgbildO1xufVxuXG5cbi8qKlxuICogTGlzdCBhbGwgcG9zc2libGUgc3VmZml4ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbLTEg4oeSIGFueV1cbiAqIEByZXR1cm5zIHhbMC4uXSwgeFsxLi5dLCB4WzIuLl0sIC4uLiBpZiBuPDA7IHhbLW4uLl0gb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogaXN1ZmZpeGVzPFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xKTogSXRlcmFibGVJdGVyYXRvcjxUW10+IHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoO1xuICBpZiAobj5YKSAgcmV0dXJuO1xuICBpZiAobj49MCkgeyB5aWVsZCB4LnNsaWNlKHgubGVuZ3RoIC0gbik7IHJldHVybjsgfVxuICBmb3IgKGxldCBpPTA7IGk8PVg7ICsraSlcbiAgICB5aWVsZCB4LnNsaWNlKGkpO1xufVxuXG5cbi8qKlxuICogT2J0YWluIGFsbCBwb3NzaWJsZSBpbmZpeGVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWy0xIOKHkiBhbnldXG4gKiBAcmV0dXJucyBbW10sIHhbMC4uMV0sIHhbMC4uMl0sIC4uLiwgeFsxLi4yXSwgLi4uXSBpZiBuPDA7IFtvbmx5IG9mIGxlbmd0aCBuXSBvdGhlcndpc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluZml4ZXM8VD4oeDogVFtdLCBuOiBudW1iZXI9LTEpOiBUW11bXSB7XG4gIHJldHVybiBbLi4uaWluZml4ZXMoeCwgbildO1xufVxuXG5cbi8qKlxuICogTGlzdCBhbGwgcG9zc2libGUgaW5maXhlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHJldHVybnMgW10sIHhbMC4uMV0sIHhbMC4uMl0sIC4uLiwgeFsxLi4yXSwgLi4uIGlmIG48MDsgb25seSBvZiBsZW5ndGggbiBvdGhlcndpc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlpbmZpeGVzPFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xKTogSXRlcmFibGVJdGVyYXRvcjxUW10+IHtcbiAgaWYgKG4+PTApIHJldHVybiBpbmZpeGVzRml4ZWQoeCwgbik7XG4gIGVsc2UgICAgICByZXR1cm4gaW5maXhlc0FsbCh4KTtcbn1cblxuZnVuY3Rpb24qIGluZml4ZXNGaXhlZDxUPih4OiBUW10sIG46IG51bWJlcik6IEl0ZXJhYmxlSXRlcmF0b3I8VFtdPiB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKG4+WCkgICByZXR1cm47XG4gIGlmIChuPT09MCkgeyB5aWVsZCBbXTsgcmV0dXJuOyB9XG4gIGZvciAobGV0IGk9MCwgST1YLW4rMTsgaTxJOyArK2kpXG4gICAgeWllbGQgeC5zbGljZShpLCBpK24pO1xufVxuXG5mdW5jdGlvbiogaW5maXhlc0FsbDxUPih4OiBUW10pOiBJdGVyYWJsZUl0ZXJhdG9yPFRbXT4ge1xuICBjb25zdCBYID0geC5sZW5ndGg7IHlpZWxkIFtdO1xuICBmb3IgKGxldCBpPTA7IGk8WDsgKytpKSB7XG4gICAgZm9yIChsZXQgaj1pKzE7IGo8PVg7ICsrailcbiAgICAgIHlpZWxkIHguc2xpY2UoaSwgaik7XG4gIH1cbn1cblxuXG4vKipcbiAqIE9idGFpbiBhbGwgcG9zc2libGUgc3Vic2VxdWVuY2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWy0xIOKHkiBhbnldXG4gKiBAcmV0dXJucyBbZWxlbWVudHMgc2VsZWN0ZWQgYnkgYml0IGZyb20gMC4uMl58eHxdIGlmIG48MDsgW29ubHkgb2YgbGVuZ3RoIG5dIG90aGVyd2lzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3Vic2VxdWVuY2VzPFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xKTogVFtdW10ge1xuICByZXR1cm4gWy4uLmlzdWJzZXF1ZW5jZXMoeCwgbildO1xufVxuXG5cbi8qKlxuICogTGlzdCBhbGwgcG9zc2libGUgc3Vic2VxdWVuY2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWy0xIOKHkiBhbnldXG4gKiBAcmV0dXJucyBlbGVtZW50cyBzZWxlY3RlZCBieSBiaXQgZnJvbSAwLi4yXnx4fCBpZiBuPDA7IG9ubHkgb2YgbGVuZ3RoIG4gb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogaXN1YnNlcXVlbmNlczxUPih4OiBUW10sIG46IG51bWJlcj0tMSk6IEl0ZXJhYmxlSXRlcmF0b3I8VFtdPiB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKG4+WCkgcmV0dXJuO1xuICBpZiAobj09PVgpICAgICAgICAgIHsgeWllbGQgeDsgIHJldHVybjsgfVxuICBpZiAobj09PTAgfHwgWD09PTApIHsgeWllbGQgW107IHJldHVybjsgfVxuICBjb25zdCB5ID0geC5zbGljZSgwLCAtMSk7XG4gIHlpZWxkKiBpc3Vic2VxdWVuY2VzKHksIG4pO1xuICBmb3IgKGNvbnN0IHMgb2YgaXN1YnNlcXVlbmNlcyh5LCBuLTEpKSB7XG4gICAgcy5wdXNoKHhbWC0xXSk7XG4gICAgeWllbGQgcztcbiAgfVxufVxuXG5cbi8qKlxuICogT2J0YWluIGFsbCBwb3NzaWJsZSBwZXJtdXRhdGlvbnMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbLTEg4oeSIGFueV1cbiAqIEByZXR1cm5zIFtbXSwgYXJyYW5nZW1lbnRzIG9mIGxlbmd0aCAxLCBvZiBsZW5ndGggMiwgLi4uXSBpZiBuPDA7IFtvbmx5IG9mIGxlbmd0aCBuXSBvdGhlcndpc2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBlcm11dGF0aW9uczxUPih4OiBUW10sIG46IG51bWJlcj0tMSk6IFRbXVtdIHtcbiAgcmV0dXJuIFsuLi5pcGVybXV0YXRpb25zKHgsIG4pXTtcbn1cblxuXG4vKipcbiAqIExpc3QgYWxsIHBvc3NpYmxlIHBlcm11dGF0aW9ucy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHJldHVybnMgW10sIGFycmFuZ2VtZW50cyBvZiBsZW5ndGggMSwgb2YgbGVuZ3RoIDIsIC4uLiBpZiBuPDA7IG9ubHkgb2YgbGVuZ3RoIG4gb3RoZXJ3aXNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiogaXBlcm11dGF0aW9uczxUPih4OiBUW10sIG46IG51bWJlcj0tMSk6IEl0ZXJhYmxlSXRlcmF0b3I8VFtdPiB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKG4+WCkgcmV0dXJuO1xuICBsZXQgICBpID0gbjwwPyAwIDogbjtcbiAgY29uc3QgSSA9IG48MD8gWCA6IG5cbiAgZm9yICg7IGk8PUk7ICsraSlcbiAgICB5aWVsZCogaXBlcm11dGF0aW9uc0ZpeGVkKHgsIGkpO1xufVxuXG5mdW5jdGlvbiogaXBlcm11dGF0aW9uc0ZpeGVkPFQ+KHg6IFRbXSwgbjogbnVtYmVyKTogSXRlcmFibGVJdGVyYXRvcjxUW10+IHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoO1xuICBpZiAoWD09PTAgfHwgbj09PTApIHsgeWllbGQgW107IHJldHVybjsgfVxuICBmb3IgKGxldCBpPTA7IGk8WDsgKytpKSB7XG4gICAgY29uc3QgeSA9IHNwbGljZSh4LCBpLCAxKTtcbiAgICBmb3IgKGNvbnN0IHAgb2YgaXBlcm11dGF0aW9uc0ZpeGVkKHksIG4tMSkpXG4gICAgICB5aWVsZCBbeFtpXSwgLi4ucF07XG4gIH1cbn1cblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgaW5kZXggb2YgYW4gaW5maXguXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgc2VhcmNoIGluZml4XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpIHwgeFtpLi5pK3x5fF0gPSB5IGVsc2UgLTFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaEluZml4PFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBudW1iZXIge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aCwgWSA9IHkubGVuZ3RoO1xuICBmb3IgKGxldCBpPTA7IGk8PVgtWTsgKytpKVxuICAgIGlmIChpc0luZml4QXQoeCwgeSwgaSwgZmMsIGZtKSkgcmV0dXJuIGk7XG4gIHJldHVybiAtMTtcbn1cblxuXG4vKipcbiAqIEZpbmQgbGFzdCBpbmRleCBvZiBhbiBpbmZpeC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBzZWFyY2ggaW5maXhcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGZpcnN0IGkgfCB4W2kuLmkrfHl8XSA9IHkgZWxzZSAtMVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoSW5maXhSaWdodDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBYID0geC5sZW5ndGgsIFkgPSB5Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT1YLVk7IGk+PTA7IC0taSlcbiAgICBpZiAoaXNJbmZpeEF0KHgsIHksIGksIGZjLCBmbSkpIHJldHVybiBpO1xuICByZXR1cm4gLTE7XG59XG5cblxuLyoqXG4gKiBGaW5kIGluZGljZXMgb2YgYW4gaW5maXguXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHkgc2VhcmNoIGluZml4XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBp4oKALCBp4oKBLCAuLi4gfCB4W2ouLmorfHl8XSA9IHk7IGog4oiIIFtp4oKALCBp4oKBLCAuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2hJbmZpeEFsbDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogbnVtYmVyW10ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aCwgWSA9IHkubGVuZ3RoLCBhID0gW107XG4gIGZvciAobGV0IGk9MDsgaTw9WC1ZOyArK2kpXG4gICAgaWYgKGlzSW5maXhBdCh4LCB5LCBpLCBmYywgZm0pKSBhLnB1c2goaSk7XG4gIHJldHVybiBhO1xufVxuXG5cbmZ1bmN0aW9uIGlzSW5maXhBdDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBpOiBudW1iZXIsIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4pOiBib29sZWFuIHtcbiAgY29uc3QgWSA9IHkubGVuZ3RoO1xuICBmb3IgKGxldCBqPTA7IGo8WTsgKytqKSB7XG4gICAgY29uc3Qgd3ggPSBmbSh4W2kral0sIGkraiwgeCk7XG4gICAgY29uc3Qgd3kgPSBmbSh5W2pdLCBqLCB5KTtcbiAgICBpZiAoZmMod3gsIHd5KSE9PTApIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxuXG4vKipcbiAqIEZpbmQgZmlyc3QgaW5kZXggb2YgYSBzdWJzZXF1ZW5jZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBzZWFyY2ggc3Vic2VxdWVuY2VcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGJlZ2luIGluZGV4IG9mIHN1YnNlcXVlbmNlLCAtMSBpZiBub3QgZm91bmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaFN1YnNlcXVlbmNlPFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBudW1iZXIge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHkxID0gWy4uLnldLm1hcChmbSksIFkgPSB5MS5sZW5ndGg7XG4gIGxldCBhID0gLTEsIGkgPSAtMSwgaiA9IDA7XG4gIGZvciAoY29uc3Qgdnggb2YgeCkge1xuICAgIGNvbnN0IHd4ID0gZm0odngsICsraSwgeCk7XG4gICAgaWYgKGZjKHd4LCB5MVtqXSkhPT0wKSBjb250aW51ZTtcbiAgICBpZiAoYTwwKSBhID0gaTtcbiAgICBpZiAoKytqPj1ZKSByZXR1cm4gYTtcbiAgfVxuICByZXR1cm4gLTE7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gUkFORE9NIEFSUkFOR0VNRU5UU1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogUGljayBhbiBhcmJpdHJhcnkgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZyIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIChbMCwgMSkpXG4gKiBAcmV0dXJucyB4W2ldIHwgaSDiiIggMC4ufHh8XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21WYWx1ZTxUPih4OiBUW10sIGZyOiBSZWFkRnVuY3Rpb248bnVtYmVyPiB8IG51bGw9TWF0aC5yYW5kb20pOiBUIHtcbiAgZnIgPSBmciB8fCBNYXRoLnJhbmRvbTtcbiAgY29uc3QgaSA9IE1hdGguZmxvb3IoZnIoKSAqIHgubGVuZ3RoKTtcbiAgcmV0dXJuIHhbaV07XG59XG5leHBvcnQge3JhbmRvbVZhbHVlIGFzIHZhbHVlfTsgIC8vIERFUFJFQ0FURURcblxuXG4vKipcbiAqIFBpY2sgYW4gYXJiaXRyYXJ5IHByZWZpeC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHBhcmFtIGZyIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIChbMCwgMSkpXG4gKiBAcmV0dXJucyB4Wy4uaV0gaWYgbjwwOyB4Wy4ubl0gb3RoZXJ3aXNlIHwgaSDiiIggMC4ufHh8XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21QcmVmaXg8VD4oeDogVFtdLCBuOiBudW1iZXI9LTEsIGZyOiBSZWFkRnVuY3Rpb248bnVtYmVyPiB8IG51bGw9TWF0aC5yYW5kb20pOiBUW10gfCBudWxsIHtcbiAgZnIgPSBmciB8fCBNYXRoLnJhbmRvbTtcbiAgY29uc3QgWCA9IHgubGVuZ3RoO1xuICBpZiAobj5YKSByZXR1cm4gbnVsbDtcbiAgbiA9IG4+PTA/IG4gOiBNYXRoLmZsb29yKChYKzEpKmZyKCkpO1xuICByZXR1cm4geC5zbGljZSgwLCBuKTtcbn1cbmV4cG9ydCB7cmFuZG9tUHJlZml4IGFzIHByZWZpeH07ICAvLyBERVBSRUNBVEVEXG5cblxuLyoqXG4gKiBQaWNrIGFuIGFyYml0cmFyeSBzdWZmaXguXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbLTEg4oeSIGFueV1cbiAqIEBwYXJhbSBmciByYW5kb20gbnVtYmVyIGdlbmVyYXRvciAoWzAsIDEpKVxuICogQHJldHVybnMgeFt8eHwtaS4uXSBpZiBuPDA7IHhbfHh8LW4uLl0gb3RoZXJ3aXNlIHwgaSDiiIggMC4ufHh8XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21TdWZmaXg8VD4oeDogVFtdLCBuOiBudW1iZXI9LTEsIGZyOiBSZWFkRnVuY3Rpb248bnVtYmVyPiB8IG51bGw9TWF0aC5yYW5kb20pOiBUW10gfCBudWxsIHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoO1xuICBpZiAobj5YKSByZXR1cm4gbnVsbDtcbiAgbiA9IG4+PTA/IG4gOiBNYXRoLmZsb29yKChYKzEpKihmciBhcyBSZWFkRnVuY3Rpb248bnVtYmVyPikoKSk7XG4gIHJldHVybiB4LnNsaWNlKFgtbik7XG59XG5leHBvcnQge3JhbmRvbVN1ZmZpeCBhcyBzdWZmaXh9OyAgLy8gREVQUkVDQVRFRFxuXG5cbi8qKlxuICogUGljayBhbiBhcmJpdHJhcnkgaW5maXguXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbLTEg4oeSIGFueV1cbiAqIEBwYXJhbSBmciByYW5kb20gbnVtYmVyIGdlbmVyYXRvciAoWzAsIDEpKVxuICogQHJldHVybnMgeFtpLi5qXSBpZiBuPDA7IHhbaS4uaStuXSBvdGhlcndpc2UgfCBpLCBqIOKIiCAwLi58eHxcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmRvbUluZml4PFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xLCBmcjogUmVhZEZ1bmN0aW9uPG51bWJlcj4gfCBudWxsPU1hdGgucmFuZG9tKTogVFtdIHwgbnVsbCB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKG4+WCkgcmV0dXJuIG51bGw7XG4gIG4gPSBuPj0wPyBuIDogcmFuZG9tSW5maXhMZW5ndGgoWCwgKGZyIGFzIFJlYWRGdW5jdGlvbjxudW1iZXI+KSgpKTtcbiAgY29uc3QgaSA9IE1hdGguZmxvb3IoKFgrMS1uKSooZnIgYXMgUmVhZEZ1bmN0aW9uPG51bWJlcj4pKCkpO1xuICByZXR1cm4geC5zbGljZShpLCBpK24pO1xufVxuZXhwb3J0IHtyYW5kb21JbmZpeCBhcyBpbmZpeH07ICAvLyBERVBSRUNBVEVEXG5cbi8vIE5vdCBhbGwgaW5maXggbGVuZ3RocyBhcmUgZXF1YWxseSBwcm9hYmxlLlxuZnVuY3Rpb24gcmFuZG9tSW5maXhMZW5ndGgoWDogbnVtYmVyLCByOiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBDID0gMC41ICogWCooWCsxKSArIDE7XG4gIGNvbnN0IG4gPSAwLjUgKiBNYXRoLnNxcnQoMSArIDgqcipDKSAtIDAuNTtcbiAgcmV0dXJuIFgrMSAgLSBNYXRoLmZsb29yKG4rMSk7XG59XG5cblxuLyoqXG4gKiBQaWNrIGFuIGFyYml0cmFyeSBzdWJzZXF1ZW5jZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFstMSDih5IgYW55XVxuICogQHBhcmFtIGZyIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIChbMCwgMSkpXG4gKiBAcmV0dXJucyB4W2ksIGosIC4uLl0gfCBbaSwgaiwgLi4uXSA9IGlzOyB8aXN8ID0gfHh8IGlmIG48MCBlbHNlIG5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmRvbVN1YnNlcXVlbmNlPFQ+KHg6IFRbXSwgbjogbnVtYmVyPS0xLCBmcjogUmVhZEZ1bmN0aW9uPG51bWJlcj4gfCBudWxsPU1hdGgucmFuZG9tKTogVFtdIHwgbnVsbCB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgaWYgKG4+WCkgIHJldHVybiBudWxsO1xuICBpZiAobj49MCkgcmV0dXJuIHJhbmRvbVN1YnNlcXVlbmNlRml4ZWQoeCwgbiwgZnIgYXMgUmVhZEZ1bmN0aW9uPG51bWJlcj4pO1xuICBlbHNlICAgICAgcmV0dXJuIHJhbmRvbVN1YnNlcXVlbmNlQWxsKHgsIGZyIGFzIFJlYWRGdW5jdGlvbjxudW1iZXI+KTtcbn1cbmV4cG9ydCB7cmFuZG9tU3Vic2VxdWVuY2UgYXMgc3Vic2VxdWVuY2V9OyAgLy8gREVQUkVDQVRFRFxuXG5mdW5jdGlvbiByYW5kb21TdWJzZXF1ZW5jZUZpeGVkPFQ+KHg6IFRbXSwgbjogbnVtYmVyLCBmcjogUmVhZEZ1bmN0aW9uPG51bWJlcj4pOiBUW10ge1xuICBjb25zdCBpcyA9IGZyb21SYW5nZSgwLCB4Lmxlbmd0aCk7XG4gIHJhbmRvbVBlcm11dGF0aW9uJChpcywgbiwgZnIpLnNvcnQoKTtcbiAgcmV0dXJuIGdldEFsbCh4LCBpcyk7XG59XG5cbmZ1bmN0aW9uIHJhbmRvbVN1YnNlcXVlbmNlQWxsPFQ+KHg6IFRbXSwgZnI6IFJlYWRGdW5jdGlvbjxudW1iZXI+KTogVFtdIHtcbiAgY29uc3QgYTogVFtdID0gW107XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmIChmcigpPDAuNSkgYS5wdXNoKHYpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIFBpY2sgYW4gYXJiaXRyYXJ5IHBlcm11dGF0aW9uLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWy0xIOKHkiBhbnldXG4gKiBAcGFyYW0gZnIgcmFuZG9tIG51bWJlciBnZW5lcmF0b3IgKFswLCAxKSlcbiAqIEByZXR1cm5zIHgnIHwgeCcgPSB4OyB2YWx1ZXMgYXJlIHJhbmRvbWx5IHNodWZmbGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21QZXJtdXRhdGlvbjxUPih4OiBUW10sIG46IG51bWJlcj0tMSwgZnI6IFJlYWRGdW5jdGlvbjxudW1iZXI+IHwgbnVsbD1NYXRoLnJhbmRvbSk6IFRbXSB8IG51bGwge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGlmIChuPlgpIHJldHVybiBudWxsO1xuICByZXR1cm4gcmFuZG9tUGVybXV0YXRpb24kKHguc2xpY2UoKSwgbiwgZnIpO1xufVxuZXhwb3J0IHtyYW5kb21QZXJtdXRhdGlvbiBhcyBwZXJtdXRhdGlvbn07ICAvLyBERVBSRUNBVEVEXG5cblxuLyoqXG4gKiBQaWNrIGFuIGFyYml0cmFyeSBwZXJtdXRhdGlvbiFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgWy0xIOKHkiBhbnldXG4gKiBAcGFyYW0gZnIgcmFuZG9tIG51bWJlciBnZW5lcmF0b3IgKFswLCAxKSlcbiAqIEByZXR1cm5zIHggfCB2YWx1ZXMgYXJlIHJhbmRvbWx5IHNodWZmbGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYW5kb21QZXJtdXRhdGlvbiQ8VD4oeDogVFtdLCBuOiBudW1iZXI9LTEsIGZyOiBSZWFkRnVuY3Rpb248bnVtYmVyPiB8IG51bGw9TWF0aC5yYW5kb20pOiBUW10ge1xuICBmciA9IGZyIHx8IE1hdGgucmFuZG9tO1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIGlmIChuPlgpIHJldHVybiB4O1xuICBuID0gbj49MD8gbiA6IE1hdGguZmxvb3IoKFgrMSkqZnIoKSk7XG4gIGZvciAobGV0IGk9MDsgaTxuOyArK2kpIHtcbiAgICBjb25zdCBqID0gaSArIE1hdGguZmxvb3IoKFgtaSkqZnIoKSk7XG4gICAgY29uc3QgdCA9IHhbaV07IHhbaV0gPSB4W2pdOyB4W2pdID0gdDtcbiAgfVxuICB4Lmxlbmd0aCA9IG47XG4gIHJldHVybiB4O1xufVxuZXhwb3J0IHtyYW5kb21QZXJtdXRhdGlvbiQgYXMgcGVybXV0YXRpb24kfTsgIC8vIERFUFJFQ0FURURcbmV4cG9ydCB7cmFuZG9tUGVybXV0YXRpb24kIGFzIHBlcm11dGUkfTtcbmV4cG9ydCB7cmFuZG9tUGVybXV0YXRpb24kIGFzIHNodWZmbGUkfTtcbi8vIC0gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRmlzaGVy4oCTWWF0ZXNfc2h1ZmZsZVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIEZJTkRcbi8vIC0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEZpbmQgZmlyc3QgdmFsdWUgcGFzc2luZyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCB2IHwgZnQodikgPSB0cnVlOyB2IOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kPFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFQge1xuICByZXR1cm4geC5maW5kKGZ0KSBhcyBUO1xufVxuXG5cbi8qKlxuICogRmluZCBsYXN0IHZhbHVlIHBhc3NpbmcgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgbGFzdCB2IHwgZnQodikgPSB0cnVlOyB2IOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaW5kUmlnaHQ8VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogVCB7XG4gIGZvciAobGV0IGk9eC5sZW5ndGgtMTsgaT49MDsgLS1pKVxuICAgIGlmIChmdCh4W2ldLCBpLCB4KSkgcmV0dXJuIHhbaV07XG4gIHJldHVybiB1bmRlZmluZWQgYXMgdW5rbm93biBhcyBUO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIFRBS0UvRFJPUFxuLy8gLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBLZWVwIGZpcnN0IG4gdmFsdWVzIG9ubHkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbMV1cbiAqIEByZXR1cm5zIHhbMC4ubl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRha2U8VD4oeDogVFtdLCBuOiBudW1iZXI9MSk6IFRbXSB7XG4gIG4gPSBNYXRoLm1heChuLCAwKTtcbiAgcmV0dXJuIHguc2xpY2UoMCwgbik7XG59XG5leHBvcnQge3Rha2UgYXMgbGVmdH07XG5cblxuLyoqXG4gKiBLZWVwIGxhc3QgbiB2YWx1ZXMgb25seS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFsxXVxuICogQHJldHVybnMgeFswLi5uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gdGFrZVJpZ2h0PFQ+KHg6IFRbXSwgbjogbnVtYmVyPTEpOiBUW10ge1xuICBjb25zdCBYID0geC5sZW5ndGg7XG4gIG4gPSBNYXRoLm1pbihNYXRoLm1heChuLCAwKSwgWCk7XG4gIHJldHVybiB4LnNsaWNlKFgtbik7XG59XG5leHBvcnQge3Rha2VSaWdodCBhcyByaWdodH07XG5cblxuLyoqXG4gKiBLZWVwIHZhbHVlcyBmcm9tIGxlZnQsIHdoaWxlIGEgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4WzAuLlQtMV0gfCBmdCh4W2ldKSA9IHRydWUg4oiAIGkg4oiIIFswLCBULTFdICYgZnQoeFtUXSkgPSBmYWxzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdGFrZVdoaWxlPFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFRbXSB7XG4gIHJldHVybiB4LnNsaWNlKDAsIHNjYW5XaGlsZSh4LCBmdCkpO1xufVxuXG5cbi8qKlxuICogS2VlcCB2YWx1ZXMgZnJvbSByaWdodCwgd2hpbGUgYSB0ZXN0IHBhc3Nlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbVC4uXSB8IGZ0KHhbaV0pID0gdHJ1ZSDiiIAgaSDiiIggW1QsIHx4fC0xXSAmIGZ0KHhbVC0xXSkgPSBmYWxzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gdGFrZVdoaWxlUmlnaHQ8VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2Uoc2NhbldoaWxlUmlnaHQoeCwgZnQpKTtcbn1cblxuXG4vKipcbiAqIERpc2NhcmQgZmlyc3QgbiB2YWx1ZXMgb25seS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiBudW1iZXIgb2YgdmFsdWVzIFsxXVxuICogQHJldHVybnMgeFtuLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkcm9wPFQ+KHg6IFRbXSwgbjogbnVtYmVyPTEpOiBUW10ge1xuICBuID0gTWF0aC5tYXgobiwgMCk7XG4gIHJldHVybiB4LnNsaWNlKG4pO1xufVxuXG5cbi8qKlxuICogRGlzY2FyZCBsYXN0IG4gdmFsdWVzIG9ubHkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbMV1cbiAqIEByZXR1cm5zIHhbMC4uLW5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkcm9wUmlnaHQ8VD4oeDogVFtdLCBuOiBudW1iZXI9MSk6IFRbXSB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgbiA9IE1hdGgubWluKE1hdGgubWF4KG4sIDApLCBYKTtcbiAgcmV0dXJuIHguc2xpY2UoMCwgWC1uKTtcbn1cblxuXG4vKipcbiAqIERpc2NhcmQgdmFsdWVzIGZyb20gbGVmdCwgd2hpbGUgYSB0ZXN0IHBhc3Nlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHhbVC4uXSB8IGZ0KHhbaV0pID0gdHJ1ZSDiiIAgaSDiiIggWzAsIFQtMV0gJiBmdCh4W1RdKSA9IGZhbHNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkcm9wV2hpbGU8VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2Uoc2NhbldoaWxlKHgsIGZ0KSk7XG59XG5cblxuLyoqXG4gKiBEaXNjYXJkIHZhbHVlcyBmcm9tIHJpZ2h0LCB3aGlsZSBhIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeFswLi5ULTFdIHwgZnQoeFtpXSkgPSB0cnVlIOKIgCBpIOKIiCBbVCwgfHh8LTFdICYgZnQoeFtULTFdKSA9IGZhbHNlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkcm9wV2hpbGVSaWdodDxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBUW10ge1xuICByZXR1cm4geC5zbGljZSgwLCBzY2FuV2hpbGVSaWdodCh4LCBmdCkpO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIFNDQU5cbi8vIC0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIFNjYW4gZnJvbSBsZWZ0LCB3aGlsZSBhIHRlc3QgcGFzc2VzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgZmlyc3QgaW5kZXggd2hlcmUgdGVzdCBmYWlsc1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2NhbldoaWxlPFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IG51bWJlciB7XG4gIGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmICghZnQodiwgKytpLCB4KSkgcmV0dXJuIGk7XG4gIHJldHVybiArK2k7XG59XG5cblxuLyoqXG4gKiBTY2FuIGZyb20gcmlnaHQsIHdoaWxlIGEgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpbmRleCB3aGVyZSB0ZXN0IHBhc3NlcyB0aWxsIGVuZFxuICovXG5leHBvcnQgZnVuY3Rpb24gc2NhbldoaWxlUmlnaHQ8VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogbnVtYmVyIHtcbiAgbGV0IGkgPSB4Lmxlbmd0aC0xO1xuICBmb3IgKDsgaT49MDsgLS1pKVxuICAgIGlmICghZnQoeFtpXSwgaSwgeCkpIGJyZWFrO1xuICByZXR1cm4gKytpO1xufVxuXG5cbi8qKlxuICogU2NhbiBmcm9tIGxlZnQsIHVudGlsIGEgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpbmRleCB3aGVyZSB0ZXN0IHBhc3Nlc1xuICovXG5leHBvcnQgZnVuY3Rpb24gc2NhblVudGlsPFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IG51bWJlciB7XG4gIGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmIChmdCh2LCArK2ksIHgpKSByZXR1cm4gaTtcbiAgcmV0dXJuICsraTtcbn1cblxuXG4vKipcbiAqIFNjYW4gZnJvbSByaWdodCwgdW50aWwgYSB0ZXN0IHBhc3Nlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIGZpcnN0IGluZGV4IHdoZXJlIHRlc3QgZmFpbHMgdGlsbCBlbmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjYW5VbnRpbFJpZ2h0PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IG51bWJlciB7XG4gIGxldCBpID0geC5sZW5ndGgtMTtcbiAgZm9yICg7IGk+PTA7IC0taSlcbiAgICBpZiAoZnQoeFtpXSwgaSwgeCkpIGJyZWFrO1xuICByZXR1cm4gKytpO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIFNFQVJDSFxuLy8gLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBGaW5kIGZpcnN0IGluZGV4IG9mIGEgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHYgc2VhcmNoIHZhbHVlXG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleCBbMF1cbiAqIEByZXR1cm5zIGluZGV4IG9mIHYgaW4geFtpLi5dIGlmIGZvdW5kIGVsc2UgLTFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluZGV4T2Y8VD4oeDogVFtdLCB2OiBULCBpOiBudW1iZXI9MCk6IG51bWJlciB7XG4gIHJldHVybiB4LmluZGV4T2YodiwgaSk7XG59XG5cblxuLyoqXG4gKiBGaW5kIGxhc3QgaW5kZXggb2YgYSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gdiBzZWFyY2ggdmFsdWVcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4IFt8eHwtMV1cbiAqIEByZXR1cm5zIGxhc3QgaW5kZXggb2YgdiBpbiB4WzAuLmldIGlmIGZvdW5kIGVsc2UgLTFcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxhc3RJbmRleE9mPFQ+KHg6IFRbXSwgdjogVCwgaTogbnVtYmVyPXgubGVuZ3RoLTEpOiBudW1iZXIge1xuICByZXR1cm4geC5sYXN0SW5kZXhPZih2LCBpKTtcbn1cblxuXG4vKipcbiAqIEZpbmQgaW5kZXggb2YgZmlyc3QgdmFsdWUgcGFzc2luZyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBmaXJzdCBpbmRleCBvZiB2YWx1ZSwgLTEgaWYgbm90IGZvdW5kXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZWFyY2g8VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogbnVtYmVyIHtcbiAgcmV0dXJuIHguZmluZEluZGV4KGZ0KTtcbn1cbmV4cG9ydCB7c2VhcmNoIGFzIGZpbmRJbmRleH07XG5cblxuLyoqXG4gKiBGaW5kIGluZGV4IG9mIGxhc3QgdmFsdWUgcGFzc2luZyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBsYXN0IGluZGV4IG9mIHZhbHVlLCAtMSBpZiBub3QgZm91bmRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlYXJjaFJpZ2h0PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IG51bWJlciB7XG4gIGZvciAobGV0IGk9eC5sZW5ndGgtMTsgaT49MDsgLS1pKVxuICAgIGlmIChmdCh4W2ldLCBpLCB4KSkgcmV0dXJuIGk7XG4gIHJldHVybiAtMTtcbn1cbmV4cG9ydCB7c2VhcmNoUmlnaHQgYXMgZmluZExhc3RJbmRleH07XG5cblxuLyoqXG4gKiBGaW5kIGluZGljZXMgb2YgdmFsdWVzIHBhc3NpbmcgYSB0ZXN0LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgaW5kaWNlcyBvZiB2YWx1ZVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2VhcmNoQWxsPFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IG51bWJlcltdIHtcbiAgbGV0IGkgPSAtMTtcbiAgY29uc3QgYTogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChjb25zdCB2IG9mIHgpXG4gICAgaWYgKGZ0KHYsICsraSwgeCkpIGEucHVzaChpKTtcbiAgcmV0dXJuIGE7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gRlVOQ1RJT05BTFxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQ2FsbCBhIGZ1bmN0aW9uIGZvciBlYWNoIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmcCBwcm9jZXNzIGZ1bmN0aW9uICh2LCBpLCB4KVxuICovXG5leHBvcnQgZnVuY3Rpb24gZm9yRWFjaDxUPih4OiBUW10sIGZwOiBQcm9jZXNzRnVuY3Rpb248VD4pOiB2b2lkIHtcbiAgeC5mb3JFYWNoKGZwKTtcbn1cblxuXG4vKipcbiAqIEV4YW1pbmUgaWYgYW55IHZhbHVlIHNhdGlzZmllcyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB0cnVlIGlmIGZ0KHbhtaIpID0gdHJ1ZSBmb3Igc29tZSB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzb21lPFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICBpZiAoZnQpIHJldHVybiB4LnNvbWUoZnQpO1xuICBlbHNlICAgIHJldHVybiBzb21lQm9vbGVhbih4KTtcbn1cbmV4cG9ydCB7c29tZSBhcyBhbnlPZn07XG5cbmZ1bmN0aW9uIHNvbWVCb29sZWFuPFQ+KHg6IFRbXSk6IGJvb2xlYW4ge1xuICBjb25zdCBJID0geC5sZW5ndGg7XG4gIGZvciAobGV0IGk9MDsgaTxJOyArK2kpXG4gICAgaWYgKHhbaV0pIHJldHVybiB0cnVlO1xuICByZXR1cm4gZmFsc2U7XG59XG5cblxuLyoqXG4gKiBFeGFtaW5lIGlmIGFsbCB2YWx1ZXMgc2F0aXNmeSBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB0cnVlIGlmIGZ0KHbhtaIpID0gdHJ1ZSBmb3IgYWxsIHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV2ZXJ5PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICBpZiAoZnQpIHJldHVybiB4LmV2ZXJ5KGZ0KTtcbiAgZWxzZSAgICByZXR1cm4gZXZlcnlCb29sZWFuKHgpO1xufVxuZXhwb3J0IHtldmVyeSBhcyBhbGxPZn07XG5cbmZ1bmN0aW9uIGV2ZXJ5Qm9vbGVhbjxUPih4OiBUW10pOiBib29sZWFuIHtcbiAgY29uc3QgSSA9IHgubGVuZ3RoO1xuICBmb3IgKGxldCBpPTA7IGk8STsgKytpKVxuICAgIGlmICgheFtpXSkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gdHJ1ZTtcbn1cblxuXG4vKipcbiAqIFRyYW5zZm9ybSB2YWx1ZXMgb2YgYW4gYXJyYXkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIFtmbSh24oKAKSwgZm0oduKCgSksIC4uLl0gfCB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXA8VCwgVT1UPih4OiBUW10sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+KTogKFR8VSlbXSB7XG4gIHJldHVybiB4Lm1hcChmbSk7XG59XG5cblxuLyoqXG4gKiBUcmFuc2Zvcm0gdmFsdWVzIG9mIGFuIGFycmF5IVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHggPSBbZm0oduKCgCksIGZtKHbigoEpLCAuLi5dOyB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtYXAkPFQ+KHg6IFRbXSwgZm06IE1hcEZ1bmN0aW9uPFQsIFQ+KTogVFtdIHtcbiAgY29uc3QgSSA9IHgubGVuZ3RoO1xuICBmb3IgKGxldCBpPTA7IGk8STsgKytpKVxuICAgIHhbaV0gPSBmbSh4W2ldLCBpLCB4KTtcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBSZWR1Y2UgdmFsdWVzIG9mIGFycmF5IHRvIGEgc2luZ2xlIHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmciByZWR1Y2UgZnVuY3Rpb24gKGFjYywgdiwgaSwgeClcbiAqIEBwYXJhbSBhY2MgaW5pdGlhbCB2YWx1ZVxuICogQHJldHVybnMgZnIoZnIoYWNjLCB24oKAKSwgduKCgSkuLi4gfCBmcihhY2MsIHbigoApID0gduKCgCBpZiBhY2Mgbm90IGdpdmVuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWR1Y2U8VCwgVT1UPih4OiBUW10sIGZyOiBSZWR1Y2VGdW5jdGlvbjxULCBUfFU+LCBhY2M/OiBUfFUpOiBUfFUge1xuICBjb25zdCBpbml0ID0gYXJndW1lbnRzLmxlbmd0aCA8PSAyO1xuICByZXR1cm4gaW5pdD8geC5yZWR1Y2UoZnIgYXMgUmVkdWNlRnVuY3Rpb248VCwgVD4pIDogeC5yZWR1Y2UoZnIgYXMgUmVkdWNlRnVuY3Rpb248VCwgVD4sIGFjYyBhcyBUKTtcbn1cblxuXG4vKipcbiAqIFJlZHVjZSB2YWx1ZXMgZnJvbSByaWdodCwgdG8gYSBzaW5nbGUgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZyIHJlZHVjZSBmdW5jdGlvbiAoYWNjLCB2LCBpLCB4KVxuICogQHBhcmFtIGFjYyBpbml0aWFsIHZhbHVlXG4gKiBAcmV0dXJucyBmcihmcihhY2MsIHbigpPigovigoApLCB24oKT4oKL4oKBKS4uLiB8IGZyKGFjYywgduKCk+KCi+KCgCkgPSB24oKT4oKL4oKAIGlmIGFjYyBub3QgZ2l2ZW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZHVjZVJpZ2h0PFQsIFU9VD4oeDogVFtdLCBmcjogUmVkdWNlRnVuY3Rpb248VCwgVHxVPiwgYWNjPzogVHxVKTogVHxVIHtcbiAgbGV0IGluaXQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDI7XG4gIGZvciAobGV0IGk9eC5sZW5ndGgtMTsgaT49MDsgLS1pKSB7XG4gICAgaWYgKGluaXQpICB7IGFjYyA9IHhbaV07IGluaXQgPSBmYWxzZTsgfVxuICAgIGVsc2UgYWNjID0gZnIoYWNjIGFzIFQgfCBVLCB4W2ldLCBpLCB4KTtcbiAgfVxuICByZXR1cm4gYWNjIGFzIFQgfCBVO1xufVxuXG5cbi8qKlxuICogS2VlcCB2YWx1ZXMgd2hpY2ggcGFzcyBhIHRlc3QuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbduKCgCwgduKCgSwgLi4uXSB8IGZ0KHbhtaIpID0gdHJ1ZTsgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVyPFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFRbXSB7XG4gIHJldHVybiB4LmZpbHRlcihmdCk7XG59XG5leHBvcnQge2ZpbHRlciBhcyBmaW5kQWxsfTtcblxuXG4vKipcbiAqIEtlZXAgdmFsdWVzIHdoaWNoIHBhc3MgYSB0ZXN0IVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4ID0gW3bigoAsIHbigoEsIC4uLl0gfCBmdCh24bWiKSA9IHRydWU7IHbhtaIg4oiIIHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbHRlciQ8VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogVFtdIHtcbiAgY29uc3QgSSA9IHgubGVuZ3RoO1xuICBsZXQgaiA9IDA7XG4gIGZvciAobGV0IGk9MDsgaTxJOyArK2kpXG4gICAgaWYgKGZ0KHhbaV0sIGksIHgpKSB4W2orK10gPSB4W2ldO1xuICB4Lmxlbmd0aCA9IGo7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogS2VlcCB2YWx1ZXMgYXQgZ2l2ZW4gaW5kaWNlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaXMgaW5kaWNlc1xuICogQHJldHVybnMgduKCgCwgduKCgSwgLi4uIHwgduG1oiA9IHhbaV07IGkg4oiIIGlzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJBdDxUPih4OiBUW10sIGlzOiBudW1iZXJbXSk6IFRbXSB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgY29uc3QgYTogVFtdID0gW107XG4gIGZvciAoY29uc3QgaSBvZiBpcylcbiAgICBpZiAoaT49MCAmJiBpPFgpIGEucHVzaCh4W2ldKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBEaXNjYXJkIHZhbHVlcyB3aGljaCBwYXNzIGEgdGVzdC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIFt24oKALCB24oKBLCAuLi5dIHwgZnQoduG1oikgPSBmYWxzZTsgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVqZWN0PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFRbXSB7XG4gIGxldCBpID0gLTE7XG4gIGNvbnN0IGE6IFRbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHYgb2YgeClcbiAgICBpZiAoIWZ0KHYsICsraSwgeCkpIGEucHVzaCh2KTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBEaXNjYXJkIHZhbHVlcyB3aGljaCBwYXNzIGEgdGVzdCFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeCA9IFt24oKALCB24oKBLCAuLi5dIHwgZnQoduG1oikgPSBmYWxzZTsgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVqZWN0JDxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBUW10ge1xuICBjb25zdCBJID0geC5sZW5ndGg7XG4gIGxldCBqID0gMDtcbiAgZm9yIChsZXQgaT0wOyBpPEk7ICsraSlcbiAgICBpZiAoIWZ0KHhbaV0sIGksIHgpKSB4W2orK10gPSB4W2ldO1xuICB4Lmxlbmd0aCA9IGo7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogRGlzY2FyZCB2YWx1ZXMgYXQgZ2l2ZW4gaW5kaWNlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaXMgaW5kaWNlc1xuICogQHJldHVybnMgW3bigoAsIHbigoEsIC4uLl0gfCB24bWiID0geFtpXTsgaSDiiIkgaXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlamVjdEF0PFQ+KHg6IFRbXSwgaXM6IG51bWJlcltdKTogVFtdIHtcbiAgbGV0IGkgPSAtMTtcbiAgY29uc3QgYTogVFtdID0gW107XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmICghaXMuaW5jbHVkZXMoKytpKSkgYS5wdXNoKHYpO1xuICByZXR1cm4gYTtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBGTEFUVEVOXG4vLyAtLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBGbGF0dGVuIG5lc3RlZCBhcnJheSB0byBnaXZlbiBkZXB0aC5cbiAqIEBwYXJhbSB4IGEgbmVzdGVkIGFycmF5XG4gKiBAcGFyYW0gbiBtYXhpbXVtIGRlcHRoIFstMSDih5IgYWxsXVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEBwYXJhbSBmdCBmbGF0dGVuIHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpIFtpc11cbiAqIEByZXR1cm5zIGZsYXQgaXRlcmFibGVcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsYXQoeDogdW5rbm93bltdLCBuOiBudW1iZXI9LTEsIGZtOiBNYXBGdW5jdGlvbjx1bmtub3duLCB1bmtub3duPiB8IG51bGw9bnVsbCwgZnQ6IFRlc3RGdW5jdGlvbjx1bmtub3duPiB8IG51bGw9bnVsbCk6IHVua25vd25bXSB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGZ0ID0gZnQgfHwgaXM7XG4gIHJldHVybiBmbGF0VG8kKFtdLCB4LCBuLCBmbSwgZnQpO1xufVxuXG5mdW5jdGlvbiBmbGF0VG8kKGE6IHVua25vd25bXSwgeDogdW5rbm93bltdLCBuOiBudW1iZXIsIGZtOiBNYXBGdW5jdGlvbjx1bmtub3duLCB1bmtub3duPiwgZnQ6IFRlc3RGdW5jdGlvbjx1bmtub3duPik6IHVua25vd25bXSB7XG4gIGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgY29uc3QgdyA9IGZtKHYsICsraSwgeCk7XG4gICAgaWYgKG4hPT0wICYmIGZ0KHcsIGksIHgpKSBmbGF0VG8kKGEsIHYgYXMgdW5rbm93bltdLCBuLTEsIGZtLCBmdCk7XG4gICAgZWxzZSBhLnB1c2godyk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBGbGF0dGVuIG5lc3RlZCBhcnJheSwgYmFzZWQgb24gbWFwIGZ1bmN0aW9uLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcGFyYW0gZnQgZmxhdHRlbiB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KSBbaXNdXG4gKiBAcmV0dXJucyBmbGF0IGl0ZXJhYmxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmbGF0TWFwKHg6IHVua25vd25bXSwgZm06IE1hcEZ1bmN0aW9uPHVua25vd24sIHVua25vd24+IHwgbnVsbD1udWxsLCBmdDogVGVzdEZ1bmN0aW9uPHVua25vd24+IHwgbnVsbD1udWxsKTogdW5rbm93bltdIHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgZnQgPSBmdCB8fCBpcztcbiAgbGV0IGkgPSAtMTtcbiAgY29uc3QgYTogdW5rbm93bltdID0gW107XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgY29uc3QgdyA9IGZtKHYsICsraSwgeCk7XG4gICAgaWYgKGZ0KHcsIGksIHgpKSBjb25jYXQkKGEsIHcgYXMgSXRlcmFibGU8dW5rbm93bj4pO1xuICAgIGVsc2UgYS5wdXNoKHcpO1xuICB9XG4gIHJldHVybiBhO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIFBSRUZJWCBTVU1cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIFBlcmZvcm0gZXhjbHVzaXZlIHByZWZpeCBzY2FuIGZyb20gbGVmdCB0byByaWdodC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnIgcmVkdWNlIGZ1bmN0aW9uIChhY2MsIHYsIGksIHgpXG4gKiBAcGFyYW0gYWNjIGluaXRpYWwgdmFsdWVcbiAqIEByZXR1cm5zIFthY2MsIGZyKGFjYywgduKCgCksIGZyKGZyKGFjYywgduKCgCksIHbigoEpLi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZXhjbHVzaXZlU2NhbjxULCBVPVQ+KHg6IFRbXSwgZnI6IFJlZHVjZUZ1bmN0aW9uPFQsIFR8VT4sIGFjYzogVHxVKTogKFR8VSlbXSB7XG4gIGNvbnN0IGE6IChUfFUpW10gPSBbXTtcbiAgY29uc3QgSSA9IHgubGVuZ3RoO1xuICBmb3IgKGxldCBpPTA7IGk8STsgKytpKSB7XG4gICAgYS5wdXNoKGFjYyk7XG4gICAgYWNjID0gZnIoYWNjLCB4W2ldLCBpLCB4KTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIFBlcmZvcm0gZXhjbHVzaXZlIHByZWZpeCBzY2FuIGZyb20gbGVmdCB0byByaWdodCFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBmciByZWR1Y2UgZnVuY3Rpb24gKGFjYywgdiwgaSwgeClcbiAqIEBwYXJhbSBhY2MgaW5pdGlhbCB2YWx1ZVxuICogQHJldHVybnMgeCA9IFthY2MsIGZyKGFjYywgduKCgCksIGZyKGZyKGFjYywgduKCgCksIHbigoEpLi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gZXhjbHVzaXZlU2NhbiQ8VD4oeDogVFtdLCBmcjogUmVkdWNlRnVuY3Rpb248VCwgVD4sIGFjYzogVCk6IFRbXSB7XG4gIGNvbnN0IEkgPSB4Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT0wOyBpPEk7ICsraSkge1xuICAgIGNvbnN0IHYgPSB4W2ldO1xuICAgIHhbaV0gPSBhY2M7XG4gICAgYWNjID0gZnIoYWNjLCB2LCBpLCB4KTtcbiAgfVxuICByZXR1cm4geDtcbn1cblxuXG4vKipcbiAqIFBlcmZvcm0gaW5jbHVzaXZlIHByZWZpeCBzY2FuIGZyb20gbGVmdCB0byByaWdodC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnIgcmVkdWNlIGZ1bmN0aW9uIChhY2MsIHYsIGksIHgpXG4gKiBAcGFyYW0gYWNjIGluaXRpYWwgdmFsdWVcbiAqIEByZXR1cm5zIFtmcihhY2MsIHbigoApLCBmcihmcihhY2MsIHbigoApLCB24oKBKS4uLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluY2x1c2l2ZVNjYW48VCwgVT1UPih4OiBUW10sIGZyOiBSZWR1Y2VGdW5jdGlvbjxULCBUfFU+LCBhY2M/OiBUfFUpOiAoVHxVKVtdIHtcbiAgbGV0IGluaXQgPSBhcmd1bWVudHMubGVuZ3RoIDw9IDI7XG4gIGNvbnN0IGE6IChUfFUpW10gPSBbXTtcbiAgY29uc3QgSSA9IHgubGVuZ3RoO1xuICBmb3IgKGxldCBpPTA7IGk8STsgKytpKSB7XG4gICAgYWNjID0gaW5pdD8geFtpXSA6IGZyKGFjYyBhcyBUfFUsIHhbaV0sIGksIHgpO1xuICAgIGEucHVzaChhY2MpO1xuICAgIGluaXQgPSBmYWxzZTtcbiAgfVxuICByZXR1cm4gYTtcbn1cbmV4cG9ydCB7aW5jbHVzaXZlU2NhbiBhcyBhY2N1bXVsYXRlfTtcblxuXG4vKipcbiAqIFBlcmZvcm0gaW5jbHVzaXZlIHByZWZpeCBzY2FuIGZyb20gbGVmdCB0byByaWdodCFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSBmciByZWR1Y2UgZnVuY3Rpb24gKGFjYywgdiwgaSwgeClcbiAqIEBwYXJhbSBhY2MgaW5pdGlhbCB2YWx1ZVxuICogQHJldHVybnMgeCA9IFtmcihhY2MsIHbigoApLCBmcihmcihhY2MsIHbigoApLCB24oKBKS4uLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluY2x1c2l2ZVNjYW4kPFQ+KHg6IFRbXSwgZnI6IFJlZHVjZUZ1bmN0aW9uPFQsIFQ+LCBhY2M6IFQpOiBUW10ge1xuICBjb25zdCBJID0geC5sZW5ndGg7XG4gIGZvciAobGV0IGk9MDsgaTxJOyArK2kpXG4gICAgYWNjID0geFtpXSA9IGZyKGFjYywgeFtpXSwgaSwgeCk7XG4gIHJldHVybiB4O1xufVxuXG5cbi8qKlxuICogQ29tYmluZSBhZGphY2VudCB2YWx1ZXMgb2YgYW4gYXJyYXkuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbWJpbmUgZnVuY3Rpb24gKHUsIHYpXG4gKiBAcGFyYW0gYWNjIGluaXRpYWwgdmFsdWVcbiAqIEByZXR1cm5zIFtmYyhhY2MsIHbigoApLCBmYyh24oKALCB24oKBKS4uLl0gfCB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGphY2VudENvbWJpbmU8VD4oeDogVFtdLCBmYzogQ29tYmluZUZ1bmN0aW9uPFQ+LCBhY2M6IFQpOiBUW10ge1xuICBjb25zdCBhOiBUW10gPSBbXTtcbiAgaWYgKHgubGVuZ3RoPjApIGEucHVzaChmYyhhY2MsIHhbMF0pKTtcbiAgY29uc3QgSSA9IHgubGVuZ3RoO1xuICBmb3IgKGxldCBpPTE7IGk8STsgKytpKVxuICAgIGEucHVzaChmYyh4W2ktMV0sIHhbaV0pKTtcbiAgcmV0dXJuIGE7XG59XG4vLyBhZGphY2VudE1hcCgpP1xuXG5cbi8qKlxuICogQ29tYmluZSBhZGphY2VudCB2YWx1ZXMgb2YgYW4gYXJyYXkhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gZmMgY29tYmluZSBmdW5jdGlvbiAodSwgdilcbiAqIEBwYXJhbSBhY2MgaW5pdGlhbCB2YWx1ZVxuICogQHJldHVybnMgeCA9IFtmYyhhY2MsIHbigoApLCBmYyh24oKALCB24oKBKS4uLl0gfCB24bWiIOKIiCB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhZGphY2VudENvbWJpbmUkPFQ+KHg6IFRbXSwgZmM6IENvbWJpbmVGdW5jdGlvbjxUPiwgYWNjOiBUKTogVFtdIHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoO1xuICBpZiAoWD09PTApIHJldHVybiB4O1xuICBsZXQgdiA9IHhbMF07XG4gIHhbMF0gID0gZmMoYWNjLCB2KTtcbiAgZm9yIChsZXQgaT0xOyBpPFg7ICsraSkge1xuICAgIGNvbnN0IHcgPSB4W2ldO1xuICAgIHhbaV0gID0gZmModiwgdyk7XG4gICAgdiA9IHc7XG4gIH1cbiAgcmV0dXJuIHg7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gQ09NQklORVxuLy8gLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogUGxhY2UgYSBzZXBhcmF0b3IgYmV0d2VlbiBldmVyeSB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gdiBzZXBhcmF0b3JcbiAqIEByZXR1cm5zIFt4WzBdLCB2LCB4WzFdLCB2LCAuLi4sIHhbfHh8LTFdXVxuICovXG5leHBvcnQgZnVuY3Rpb24gaW50ZXJzcGVyc2U8VD4oeDogVFtdLCB2OiBUKTogVFtdIHtcbiAgY29uc3QgYTogVFtdID0gW107IGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdSBvZiB4KSB7XG4gICAgaWYgKCsraT4wKSBhLnB1c2godik7XG4gICAgYS5wdXNoKHUpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogRXN0aW1hdGUgbmV3IHZhbHVlcyBiZXR3ZWVuIGV4aXN0aW5nIG9uZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZjIGNvbWJpbmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcmV0dXJucyBbeFswXSwgZmMoeFswXSwgeFsxXSksIHhbMV0sIGZjKHhbMV0sIHhbMl0pLCAuLi4sIHhbfHh8LTFdXVxuICovXG5leHBvcnQgZnVuY3Rpb24gaW50ZXJwb2xhdGU8VD4oeDogVFtdLCBmYzogQ29tYmluZUZ1bmN0aW9uPFQ+KTogVFtdIHtcbiAgY29uc3QgYSA9IFtdO1xuICBsZXQgdTogVCA9IHVuZGVmaW5lZCBhcyBUO1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmICgrK2k+MCkgYS5wdXNoKGZjKHUsIHYpKTtcbiAgICBhLnB1c2godSA9IHYpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogUGxhY2UgdmFsdWVzIG9mIGFuIGFycmF5IGJldHdlZW4gYW5vdGhlci5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBhbm90aGVyIGFycmF5XG4gKiBAcGFyYW0gbSBudW1iZXIgb2YgdmFsdWVzIGZyb20geCBbMV1cbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgZnJvbSB5IFsxXVxuICogQHBhcmFtIHMgc3RlcCBzaXplIGZvciB4IFttXVxuICogQHBhcmFtIHQgc3RlcCBzaXplIGZvciB5IFtuXVxuICogQHJldHVybnMgeFswLi5tXSDip7ogeVswLi5uXSDip7ogeFtzLi5zK21dIOKnuiB5W3QuLnQrbl0g4qe6IC4uLiDip7ogeFtrKnMuLnx4fC0xXSB8IGsg4oiIIFdcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGludGVybWl4PFQ+KHg6IFRbXSwgeTogVFtdLCBtOiBudW1iZXI9MSwgbjogbnVtYmVyPTEsIHM6IG51bWJlcj1tLCB0OiBudW1iZXI9bik6IFRbXSB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgY29uc3QgWSA9IHkubGVuZ3RoO1xuICBjb25zdCBhOiBUW10gPSBbXTtcbiAgbSA9IE1hdGgubWF4KG0sIDApO1xuICBuID0gTWF0aC5tYXgobiwgMCk7XG4gIHMgPSBNYXRoLm1heChzLCAxKTtcbiAgdCA9IE1hdGgubWF4KHQsIDEpO1xuICBmb3IgKGxldCBpPTAsIGo9MDsgaTxYOyBpKz1zKSB7XG4gICAgaWYgKGk+MCkge1xuICAgICAgZm9yIChsZXQgaz1qLCBLPWsrbjsgazxLOyArK2spXG4gICAgICAgIGEucHVzaCh5W2sgJSBZXSk7XG4gICAgICBqICs9IHQ7XG4gICAgfVxuICAgIGNvbmNhdCQoYSwgeC5zbGljZShpLCBpK20pKTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIFBsYWNlIHZhbHVlcyBmcm9tIGl0ZXJhYmxlcyBhbHRlcm5hdGVseS5cbiAqIEBwYXJhbSB4cyBhcnJheXNcbiAqIEByZXR1cm5zIFt44oKAWzBdLCB44oKBWzBdLCAuLi4sIHjigoBbMV0sIHjigoFbMF0sIC4uLl0gfCBbeOKCgCwgeOKCgSwgLi4uXSA9IHhzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcmxlYXZlPFQ+KHhzOiBUW11bXSk6IFRbXSB7XG4gIGNvbnN0IGE6IFRbXSA9IFtdO1xuICBmb3IgKGxldCBpPTA7OyArK2kpIHtcbiAgICBsZXQgbiA9IDA7XG4gICAgZm9yIChjb25zdCB4IG9mIHhzKVxuICAgICAgaWYgKGk8eC5sZW5ndGgpIHsgYS5wdXNoKHhbaV0pOyArK247IH1cbiAgICBpZiAobj09PTApIGJyZWFrO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogQ29tYmluZSB2YWx1ZXMgZnJvbSBhcnJheXMuXG4gKiBAcGFyYW0geHMgYXJyYXlzXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2cywgaSlcbiAqIEBwYXJhbSBmZSBlbmQgZnVuY3Rpb24gKGRvbmVzKSBbc29tZV1cbiAqIEBwYXJhbSB2ZCBkZWZhdWx0IHZhbHVlXG4gKiBAcmV0dXJucyBbZm0oW3jigoBbMF0sIHjigoFbMF0sIC4uLl0pLCBmbShbeOKCgFsxXSwgeOKCgVsxXSwgLi4uXSksIC4uLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHppcDxULCBVPVRbXT4oeHM6IFRbXVtdLCBmbTogTWFwRnVuY3Rpb248VFtdLCBUW118VT4gfCBudWxsPW51bGwsIGZlOiBFbmRGdW5jdGlvbiB8IG51bGw9bnVsbCwgdmQ/OiBUKTogKFRbXXxVKVtdIHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgZmUgPSBmZSB8fCBzb21lIGFzIEVuZEZ1bmN0aW9uO1xuICBjb25zdCBYID0geHMubGVuZ3RoLCBhOiAoVFtdfFUpW10gPSBbXTtcbiAgaWYgKFg9PT0wKSByZXR1cm4gYTtcbiAgY29uc3QgZHMgPSBuZXcgQXJyYXkoWCkuZmlsbChmYWxzZSk7XG4gIGNvbnN0IGxzID0geHMubWFwKHggPT4geC5sZW5ndGgpO1xuICBmb3IgKGxldCBpPTA7OyArK2kpIHtcbiAgICBjb25zdCB2czogVFtdID0gW107XG4gICAgZm9yIChsZXQgaj0wOyBqPFg7ICsraikge1xuICAgICAgZHNbal0gPSBpPj1sc1tqXTtcbiAgICAgIHZzW2pdID0gZHNbal0/IHZkIGFzIFQgOiB4c1tqXVtpXTtcbiAgICB9XG4gICAgaWYgKGZlKGRzKSkgYnJlYWs7XG4gICAgYS5wdXNoKGZtKHZzLCBpLCBudWxsKSk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLy8gVE9ETzogemlwMigpP1xuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIE1BTklQVUxBVElPTlxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBGaWxsIHdpdGggZ2l2ZW4gdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHYgdmFsdWVcbiAqIEBwYXJhbSBpIGJlZ2luIGluZGV4IFswXVxuICogQHBhcmFtIEkgZW5kIGluZGV4IFt8eHxdXG4gKiBAcmV0dXJucyB4JyB8IHgnID0geDsgeCdbaS4uSV0gPSB2XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaWxsPFQ+KHg6IFRbXSwgdjogVCwgaTogbnVtYmVyPTAsIEk6IG51bWJlcj14Lmxlbmd0aCk6IFRbXSB7XG4gIHJldHVybiB4LnNsaWNlKCkuZmlsbCh2LCBpLCBJKTtcbn1cblxuXG4vKipcbiAqIEZpbGwgd2l0aCBnaXZlbiB2YWx1ZSFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSB2IHZhbHVlXG4gKiBAcGFyYW0gaSBiZWdpbiBpbmRleCBbMF1cbiAqIEBwYXJhbSBJIGVuZCBpbmRleCBbfHh8XVxuICogQHJldHVybnMgeCB8IHhbaS4uSV0gPSB2XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaWxsJDxUPih4OiBUW10sIHY6IFQsIGk6IG51bWJlcj0wLCBJOiBudW1iZXI9eC5sZW5ndGgpOiBUW10ge1xuICByZXR1cm4geC5maWxsKHYsIGksIEkpO1xufVxuXG5cbi8qKlxuICogQWRkIHZhbHVlIHRvIHRoZSBlbmQuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHZzIHZhbHVlcyB0byBhZGRcbiAqIEByZXR1cm5zIHgg4qe6IHZzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwdXNoPFQ+KHg6IFRbXSwgLi4udnM6IFRbXSk6IFRbXSB7XG4gIHJldHVybiB4LmNvbmNhdCh2cyk7XG59XG5leHBvcnQge3B1c2ggYXMgcHVzaEJhY2t9O1xuZXhwb3J0IHtwdXNoIGFzIGFwcGVuZH07XG5cblxuLyoqXG4gKiBBZGQgdmFsdWVzIHRvIHRoZSBlbmQhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gdnMgdmFsdWVzIHRvIGFkZFxuICogQHJldHVybnMgeCA9IHgg4qe6IHZzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBwdXNoJDxUPih4OiBUW10sIC4uLnZzOiBUW10pOiBUW10ge1xuICB4LnB1c2goLi4udnMpO1xuICByZXR1cm4geDtcbn1cbmV4cG9ydCB7cHVzaCQgYXMgcHVzaEJhY2skfTtcbmV4cG9ydCB7cHVzaCQgYXMgYXBwZW5kJH07XG5cblxuLyoqXG4gKiBSZW1vdmUgbGFzdCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcmV0dXJucyB4WzAuLnx4fC0xXVxuICovXG5leHBvcnQgZnVuY3Rpb24gcG9wPFQ+KHg6IFRbXSk6IFRbXSB7XG4gIHJldHVybiB4LnNsaWNlKDAsIC0xKTtcbn1cbmV4cG9ydCB7cG9wIGFzIHBvcEJhY2t9O1xuXG5cbi8qKlxuICogUmVtb3ZlIGxhc3QgdmFsdWUhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcmV0dXJucyB4ID0geFswLi58eHwtMV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBvcCQ8VD4oeDogVFtdKTogVFtdIHtcbiAgeC5wb3AoKTtcbiAgcmV0dXJuIHg7XG59XG5leHBvcnQge3BvcCBhcyBwb3BCYWNrJH07XG5cblxuLyoqXG4gKiBSZW1vdmUgZmlyc3QgdmFsdWUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHJldHVybnMgeFsxLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaGlmdDxUPih4OiBUW10pOiBUW10ge1xuICByZXR1cm4geC5zbGljZSgxKTtcbn1cbmV4cG9ydCB7c2hpZnQgYXMgcG9wRnJvbnR9O1xuXG5cbi8qKlxuICogUmVtb3ZlIGZpcnN0IHZhbHVlIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHJldHVybnMgeCA9IHhbMS4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc2hpZnQkPFQ+KHg6IFRbXSk6IFRbXSB7XG4gIHguc2hpZnQoKTtcbiAgcmV0dXJuIHg7XG59XG5leHBvcnQge3NoaWZ0JCBhcyBwb3BGcm9udCR9O1xuXG5cbi8qKlxuICogQWRkIHZhbHVlcyB0byB0aGUgc3RhcnQuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIHZzIHZhbHVlcyB0byBhZGRcbiAqIEByZXR1cm5zIHZzIOKnuiB4XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bnNoaWZ0PFQ+KHg6IEl0ZXJhYmxlPFQ+LCAuLi52czogVFtdKTogVFtdIHtcbiAgcmV0dXJuIGNvbmNhdCQodnMsIHgpO1xufVxuZXhwb3J0IHt1bnNoaWZ0IGFzIHB1c2hGcm9udH07XG5leHBvcnQge3Vuc2hpZnQgYXMgcHJlcGVuZH07XG5cblxuLyoqXG4gKiBBZGQgdmFsdWVzIHRvIHRoZSBzdGFydCFcbiAqIEBwYXJhbSB4IGFuIGFycmF5ICh1cGRhdGVkISlcbiAqIEBwYXJhbSB2cyB2YWx1ZXMgdG8gYWRkXG4gKiBAcmV0dXJucyB4ID0gdnMg4qe6IHhcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVuc2hpZnQkPFQ+KHg6IFRbXSwgLi4udnM6IFRbXSk6IFRbXSB7XG4gIHgudW5zaGlmdCguLi52cyk7XG4gIHJldHVybiB4O1xufVxuZXhwb3J0IHt1bnNoaWZ0JCBhcyBwdXNoRnJvbnQkfTtcbmV4cG9ydCB7dW5zaGlmdCQgYXMgcHJlcGVuZCR9O1xuXG5cbi8qKlxuICogQ29weSBwYXJ0IG9mIGFycmF5IHRvIGFub3RoZXIuXG4gKiBAcGFyYW0geCB0YXJnZXQgYXJyYXlcbiAqIEBwYXJhbSB5IHNvdXJjZSBhcnJheVxuICogQHBhcmFtIGogd3JpdGUgaW5kZXggWzBdXG4gKiBAcGFyYW0gaSByZWFkIGJlZ2luIGluZGV4IFswXVxuICogQHBhcmFtIEkgcmVhZCBlbmQgaW5kZXggW3x4fF1cbiAqIEByZXR1cm5zIHhbMC4ual0g4qe6IHlbaS4uSV0g4qe6IHhbaitJLWkuLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvcHk8VD4oeDogVFtdLCB5OiBUW10sIGo6IG51bWJlcj0wLCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPXkubGVuZ3RoKTogVFtdIHtcbiAgcmV0dXJuIGNvcHkkKHguc2xpY2UoKSwgeSwgaiwgaSwgSSk7XG59XG5cblxuLyoqXG4gKiBDb3B5IHBhcnQgb2YgYXJyYXkgdG8gYW5vdGhlciFcbiAqIEBwYXJhbSB4IHRhcmdldCBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0geSBzb3VyY2UgYXJyYXlcbiAqIEBwYXJhbSBqIHdyaXRlIGluZGV4IFswXVxuICogQHBhcmFtIGkgcmVhZCBiZWdpbiBpbmRleCBbMF1cbiAqIEBwYXJhbSBJIHJlYWQgZW5kIGluZGV4IFt8eHxdXG4gKiBAcmV0dXJucyB4ID0geFswLi5qXSDip7ogeVtpLi5JXSDip7ogeFtqK0ktaS4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29weSQ8VD4oeDogVFtdLCB5OiBUW10sIGo6IG51bWJlcj0wLCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPXkubGVuZ3RoKTogVFtdIHtcbiAgaiA9IGluZGV4KHgsIGopO1xuICBbaSwgSV0gPSBpbmRleFJhbmdlKHksIGksIEkpO1xuICBmb3IgKDsgaTxJOyArK2ksICsrailcbiAgICB4W2pdID0geVtpXTtcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBDb3B5IHBhcnQgb2YgYXJyYXkgd2l0aGluLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBqIHdyaXRlIGluZGV4IFswXVxuICogQHBhcmFtIGkgcmVhZCBiZWdpbiBpbmRleCBbMF1cbiAqIEBwYXJhbSBJIHJlYWQgZW5kIGluZGV4IFt8eHxdXG4gKiBAcmV0dXJucyB4WzAuLmpdIOKnuiB4W2kuLkldIOKnuiB4W2orSS1pLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3B5V2l0aGluPFQ+KHg6IFRbXSwgajogbnVtYmVyPTAsIGk6IG51bWJlcj0wLCBJOiBudW1iZXI9eC5sZW5ndGgpOiBUW10ge1xuICByZXR1cm4geC5zbGljZSgpLmNvcHlXaXRoaW4oaiwgaSwgSSk7XG59XG5cblxuLyoqXG4gKiBDb3B5IHBhcnQgb2YgYXJyYXkgd2l0aGluIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGogd3JpdGUgaW5kZXggWzBdXG4gKiBAcGFyYW0gaSByZWFkIGJlZ2luIGluZGV4IFswXVxuICogQHBhcmFtIEkgcmVhZCBlbmQgaW5kZXggW3x4fF1cbiAqIEByZXR1cm5zIHggPSB4WzAuLmpdIOKnuiB4W2kuLkldIOKnuiB4W2orSS1pLi5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb3B5V2l0aGluJDxUPih4OiBUW10sIGo6IG51bWJlcj0wLCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPXgubGVuZ3RoKTogVFtdIHtcbiAgcmV0dXJuIHguY29weVdpdGhpbihqLCBpLCBJKTtcbn1cblxuXG4vKipcbiAqIE1vdmUgcGFydCBvZiBhcnJheSB3aXRoaW4uXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGogd3JpdGUgaW5kZXggWzBdXG4gKiBAcGFyYW0gaSByZWFkIGJlZ2luIGluZGV4IFswXVxuICogQHBhcmFtIEkgcmVhZCBlbmQgaW5kZXggW3x4fF1cbiAqIEByZXR1cm5zIHhbMC4ual0g4qe6IHhbaS4uSV0g4qe6IHhbai4uaV0g4qe6IHhbSS4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gbW92ZVdpdGhpbjxUPih4OiBUW10sIGo6IG51bWJlcj0wLCBpOiBudW1iZXI9MCwgSTogbnVtYmVyPXgubGVuZ3RoKTogVFtdIHtcbiAgaiA9IGluZGV4KHgsIGopO1xuICBbaSwgSV0gPSBpbmRleFJhbmdlKHgsIGksIEkpO1xuICBpZiAoajxpKSByZXR1cm4gbW92ZVBhcnQoeCwgaiwgaSwgSSk7XG4gIGVsc2UgICAgIHJldHVybiBtb3ZlUGFydCh4LCBpLCBJLCBqKTtcbn1cblxuZnVuY3Rpb24gbW92ZVBhcnQ8VD4oeDogVFtdLCBpOiBudW1iZXIsIGo6IG51bWJlciwgazogbnVtYmVyKTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2UoMCwgaSkuY29uY2F0KFxuICAgIHguc2xpY2UoaiwgayksXG4gICAgeC5zbGljZShpLCBqKSxcbiAgICB4LnNsaWNlKGspXG4gICk7XG59XG5cblxuLyoqXG4gKiBNb3ZlIHBhcnQgb2YgYXJyYXkgd2l0aGluIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGogd3JpdGUgwrFpbmRleCBbMF1cbiAqIEBwYXJhbSBpIHJlYWQgYmVnaW4gwrFpbmRleCBbMF1cbiAqIEBwYXJhbSBJIHJlYWQgZW5kIMKxaW5kZXggW3x4fF1cbiAqIEByZXR1cm5zIHggPSB4WzAuLmpdIOKnuiB4W2kuLkldIOKnuiB4W2ouLmldIOKnuiB4W0kuLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vdmVXaXRoaW4kPFQ+KHg6IFRbXSwgajogbnVtYmVyPTAsIGk6IG51bWJlcj0wLCBJOiBudW1iZXI9eC5sZW5ndGgpOiBUW10ge1xuICBqID0gaW5kZXgoeCwgaik7XG4gIFtpLCBJXSA9IGluZGV4UmFuZ2UoeCwgaSwgSSk7XG4gIGNvbnN0IHAgPSAgeC5zbGljZShpLCBJKSwgUCA9IHAubGVuZ3RoO1xuICBpZiAoajxpKSB4LmNvcHlXaXRoaW4oaitQLCBqLCBpKTtcbiAgZWxzZSAgICAgeC5jb3B5V2l0aGluKGksICAgSSwgaik7XG4gIHJldHVybiBjb3B5JCh4LCBwLCBqPGk/IGogOiBqLVApO1xufVxuLy8gRE9VQlQ6IEFyZSBuZWdhdGl2ZSBpbmRpY2VzIGFueSBoZWxwZnVsIChvdGhlciB0aGFuIGJhc2ljIHNob3J0Y3V0cyk/XG4vLyBET1VCVDogSXQgaXMgbm90IGVhc3kgdG8gdXNlIGEgbmVnYXRpdmUgaW5kZXggc3VwcG9ydGluZyBmdW5jdGlvbiBmcm9tIGFub3RoZXIgbmVnYXRpdmUgaW5kZXggc3VwcG9ydGluZyBmdW5jdGlvbi5cbi8vIERPVUJUOiBTZWVtcyB0byBtZSB0aGV5IGFyZSBvbmx5IGNvbXBsaWNhdGluZyBpbXBsZW1lbnRhdGlvbiBvZiBhbGdvcml0aG1zLCBhbmQgc2hvdWxkIGJlIHJlbW92ZWQuXG5cblxuLyoqXG4gKiBSZW1vdmUgb3IgcmVwbGFjZSBleGlzdGluZyB2YWx1ZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGkgcmVtb3ZlIMKxaW5kZXhcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgdG8gcmVtb3ZlIFtyZXN0XVxuICogQHBhcmFtIHZzIHZhbHVlcyB0byBpbnNlcnRcbiAqIEByZXR1cm5zIHhbMC4uaV0g4qe6IHZzIOKnuiB4W2krbi4uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gc3BsaWNlPFQ+KHg6IFRbXSwgaTogbnVtYmVyLCBuOiBudW1iZXI9eC5sZW5ndGgsIC4uLnZzOiBUW10pOiBUW10ge1xuICBpID0gaW5kZXgoeCwgaSk7XG4gIG4gPSBNYXRoLm1heChuLCAwKTtcbiAgcmV0dXJuIGNvbmNhdCQoeC5zbGljZSgwLCBpKSwgdnMsIHguc2xpY2UoaStuKSk7XG59XG5leHBvcnQge3NwbGljZSBhcyB0b1NwbGljZWR9O1xuXG5cbi8qKlxuICogUmVtb3ZlIG9yIHJlcGxhY2UgZXhpc3RpbmcgdmFsdWVzIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIGkgcmVtb3ZlIMKxaW5kZXhcbiAqIEBwYXJhbSBuIG51bWJlciBvZiB2YWx1ZXMgdG8gcmVtb3ZlIFtyZXN0XVxuICogQHBhcmFtIHZzIHZhbHVlcyB0byBpbnNlcnRcbiAqIEByZXR1cm5zIHggPSB4WzAuLmldIOKnuiB2cyDip7ogeFtpK24uLl1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNwbGljZSQ8VD4oeDogVFtdLCBpOiBudW1iZXIsIG46IG51bWJlcj14Lmxlbmd0aCwgLi4udnM6IFRbXSk6IFRbXSB7XG4gIHguc3BsaWNlKGksIG4sIC4uLnZzKTtcbiAgcmV0dXJuIHg7XG59XG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gQ09VTlQvUEFSVElUSU9OXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIENvdW50IHZhbHVlcyB3aGljaCBzYXRpc2Z5IGEgdGVzdC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIM6jdOG1oiB8IHThtaIgPSAxIGlmIGZ0KHbhtaIpIGVsc2UgMDsgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gY291bnQ8VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogbnVtYmVyIHtcbiAgbGV0IGkgPSAtMSwgYSA9IDA7XG4gIGZvciAoY29uc3QgdiBvZiB4KVxuICAgIGlmIChmdCh2LCArK2ksIHgpKSArK2E7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogQ291bnQgb2NjdXJyZW5jZXMgb2YgZWFjaCBkaXN0aW5jdCB2YWx1ZS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgTWFwIFxce3ZhbHVlIOKHkiBjb3VudFxcfVxuICovXG5leHBvcnQgZnVuY3Rpb24gY291bnRFYWNoPFQsIFU9VD4oeDogVFtdLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IE1hcDxUfFUsIG51bWJlcj4ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBsZXQgaSAgPSAtMTsgY29uc3QgYSA9IG5ldyBNYXAoKTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBjb25zdCB3ID0gZm0odiwgKytpLCB4KTtcbiAgICBhLnNldCh3LCAoYS5nZXQodykgfHwgMCkgKyAxKTtcbiAgfVxuICByZXR1cm4gYTtcbn1cbmV4cG9ydCB7Y291bnRFYWNoIGFzIGNvdW50QXN9OyAgLy8gREVQUkVDQVRFRFxuXG5cbi8qKlxuICogU2VncmVnYXRlIHZhbHVlcyBieSB0ZXN0IHJlc3VsdC5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZnQgdGVzdCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIFtzYXRpc2ZpZXMsIGRvZXNudF1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnRpdGlvbjxUPih4OiBUW10sIGZ0OiBUZXN0RnVuY3Rpb248VD4pOiBbVFtdLCBUW11dIHtcbiAgY29uc3QgdDogVFtdID0gW10sIGY6IFRbXSA9IFtdO1xuICBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGlmIChmdCh2LCArK2ksIHgpKSB0LnB1c2godik7XG4gICAgZWxzZSBmLnB1c2godik7XG4gIH1cbiAgcmV0dXJuIFt0LCBmXTtcbn1cblxuXG4vKipcbiAqIFNlZ3JlZ2F0ZSBlYWNoIGRpc3RpbmN0IHZhbHVlLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBNYXAgXFx7a2V5IOKHkiB2YWx1ZXNcXH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnRpdGlvbkVhY2g8VCwgVT1UPih4OiBUW10sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogTWFwPFR8VSwgVFtdPiB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGxldCBpICA9IC0xOyBjb25zdCBhID0gbmV3IE1hcDxUfFUsIFRbXT4oKTtcbiAgZm9yIChjb25zdCB2IG9mIHgpIHtcbiAgICBjb25zdCB3ID0gZm0odiwgKytpLCB4KTtcbiAgICBpZiAoIWEuaGFzKHcpKSBhLnNldCh3LCBbXSk7XG4gICAgYS5nZXQodykhLnB1c2godik7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5leHBvcnQge3BhcnRpdGlvbkVhY2ggYXMgZ3JvdXBUb01hcH07XG5leHBvcnQge3BhcnRpdGlvbkVhY2ggYXMgcGFydGl0aW9uQXN9OyAgICAvLyBERVBSRUNBVEVEXG4vLyAjZW5kcmVnaW9uXG5cblxuXG5cbi8vICNyZWdpb24gU1BMSVRTXG4vLyAtLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEJyZWFrIGFycmF5IGNvbnNpZGVyaW5nIHRlc3QgYXMgc2VwYXJhdG9yLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBmdCB0ZXN0IGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgW3hbai4ua10sIHhbbC4ubV0sIC4uLl0gfCBmdCh4W2ldKSA9IHRydWU7IGkgPSAwLi5qIC8gay4ubCAvIC4uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3BsaXQ8VD4oeDogVFtdLCBmdDogVGVzdEZ1bmN0aW9uPFQ+KTogVFtdW10ge1xuICBsZXQgaSA9IC0xO1xuICBjb25zdCBhOiBUW11bXSA9IFtdO1xuICBsZXQgYjogVFtdID0gW107XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgaWYgKCFmdCh2LCArK2ksIHgpKSAgYi5wdXNoKHYpO1xuICAgIGVsc2UgaWYgKGIubGVuZ3RoKSB7IGEucHVzaChiKTsgYiA9IFtdOyB9XG4gIH1cbiAgaWYgKGIubGVuZ3RoKSBhLnB1c2goYik7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogQnJlYWsgYXJyYXkgY29uc2lkZXJpbmcgaW5kaWNlcyBhcyBzZXBhcmF0b3IuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGlzIGluZGljZXMgKHNvcnRlZClcbiAqIEByZXR1cm5zIFt4W2ouLmtdLCB4W2wuLm1dLCAuLi5dIHwgZnQoeFtpXSkgPSB0cnVlOyBpID0gMC4uaiAvIGsuLmwgLyAuLi47IGkg4oiIIGlzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcGxpdEF0PFQ+KHg6IFRbXSwgaXM6IG51bWJlcltdKTogVFtdW10ge1xuICBsZXQgaSA9IC0xO1xuICBjb25zdCBhOiBUW11bXSA9IFtdO1xuICBsZXQgYjogVFtdID0gW107XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgaWYgKCFpcy5pbmNsdWRlcygrK2kpKSBiLnB1c2godik7XG4gICAgZWxzZSBpZihiLmxlbmd0aCkgICAgeyBhLnB1c2goYik7IGIgPSBbXTsgfVxuICB9XG4gIGlmIChiLmxlbmd0aCkgYS5wdXNoKGIpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEJyZWFrIGFycmF5IHdoZW4gdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbeFswLi5qXSwgeFtqLi5rXSwgLi4uXSB8IGZ0KHhbaV0pID0gdHJ1ZTsgaSA9IGosIGssIC4uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3V0PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFRbXVtdIHtcbiAgbGV0IGogPSAwOyBjb25zdCBhID0gW107XG4gIGNvbnN0IEkgPSB4Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT0wOyBpPEk7ICsraSkge1xuICAgIGlmICghZnQoeFtpXSwgaSwgeCkpIGNvbnRpbnVlO1xuICAgIGEucHVzaCh4LnNsaWNlKGosIGkpKTtcbiAgICBqID0gaTtcbiAgfVxuICBhLnB1c2goeC5zbGljZShqKSk7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogQnJlYWsgYXJyYXkgYWZ0ZXIgdGVzdCBwYXNzZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGZ0IHRlc3QgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbeFswLi5qKzFdLCB4W2orMS4ua10sIC4uLl0gfCBmdCh4W2ldKSA9IHRydWU7IGkgPSBqLCBrLCAuLi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGN1dFJpZ2h0PFQ+KHg6IFRbXSwgZnQ6IFRlc3RGdW5jdGlvbjxUPik6IFRbXVtdIHtcbiAgbGV0IGogPSAwOyBjb25zdCBhID0gW107XG4gIGNvbnN0IEkgPSB4Lmxlbmd0aDtcbiAgZm9yIChsZXQgaT0wOyBpPEk7ICsraSkge1xuICAgIGlmICghZnQoeFtpXSwgaSwgeCkpIGNvbnRpbnVlO1xuICAgIGEucHVzaCh4LnNsaWNlKGosIGkrMSkpO1xuICAgIGogPSBpKzE7XG4gIH1cbiAgYS5wdXNoKHguc2xpY2UoaikpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEJyZWFrIGFycmF5IGF0IGdpdmVuIGluZGljZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGlzIHNwbGl0IMKxaW5kaWNlcyAobGVmdCB0byByaWdodClcbiAqIEByZXR1cm5zIFt4WzAuLmpdLCB4W2ouLmtdLCAuLi5dIHwgZnQoeFtpXSkgPSB0cnVlOyBpID0gaiwgaywgLi4uOyBpIOKIiCBpc1xuICovXG5leHBvcnQgZnVuY3Rpb24gY3V0QXQ8VD4oeDogVFtdLCBpczogbnVtYmVyW10pOiBUW11bXSB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgbGV0IGogPSAwOyBjb25zdCBhID0gW107XG4gIGZvciAobGV0IGkgb2YgaXMpIHtcbiAgICBpID0gaTwwPyBYK2kgOiBpO1xuICAgIGEucHVzaCh4LnNsaWNlKGosIGkpKTtcbiAgICBqID0gTWF0aC5tYXgoaiwgaSk7XG4gIH1cbiAgYS5wdXNoKHguc2xpY2UoaikpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEJyZWFrIGFycmF5IGFmdGVyIGdpdmVuIGluZGljZXMuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIGlzIHNwbGl0IMKxaW5kaWNlcyAobGVmdCB0byByaWdodClcbiAqIEByZXR1cm5zIFt4WzAuLmorMV0sIHhbaisxLi5rXSwgLi4uXSB8IGZ0KHhbaV0pID0gdHJ1ZTsgaSA9IGosIGssIC4uLjsgaSDiiIggaXNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGN1dEF0UmlnaHQ8VD4oeDogVFtdLCBpczogbnVtYmVyW10pOiBUW11bXSB7XG4gIGNvbnN0IFggPSB4Lmxlbmd0aDtcbiAgbGV0IGogPSAwOyBjb25zdCBhID0gW107XG4gIGZvciAobGV0IGkgb2YgaXMpIHtcbiAgICBpID0gaTwwPyBYK2kgOiBpO1xuICAgIGEucHVzaCh4LnNsaWNlKGosIGkrMSkpO1xuICAgIGogPSBNYXRoLm1heChqLCBpKzEpO1xuICB9XG4gIGEucHVzaCh4LnNsaWNlKGopKTtcbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBLZWVwIHNpbWlsYXIgdmFsdWVzIHRvZ2V0aGVyIGFuZCBpbiBvcmRlci5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyBbeFswLi5rXSwgeFtrLi5sXSwgLi4uXSB8IGZjKHhbaV0sIHhbal0pID0gMDsgaSwgaiA9IDAuLmsgLyBrLi5sIC8gLi4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBncm91cDxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXVtdIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBhOiBUW11bXSA9IFtdO1xuICBsZXQgYjogVFtdID0gW107XG4gIGxldCB1OiBUfFUgPSB1bmRlZmluZWQgYXMgVCwgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHcgPSBmbSh2LCArK2ksIHgpO1xuICAgIGlmIChpPT09MCB8fCBmYyh1LCB3KT09PTApIGIucHVzaCh2KTtcbiAgICBlbHNlIHsgYS5wdXNoKGIpOyBiID0gW3ZdOyB9XG4gICAgdSA9IHc7XG4gIH1cbiAgYS5wdXNoKGIpO1xuICByZXR1cm4gYTtcbn1cblxuXG4vKipcbiAqIEJyZWFrIGFycmF5IGludG8gY2h1bmtzIG9mIGdpdmVuIHNpemUuXG4gKiBAcGFyYW0geCBhbiBhcnJheVxuICogQHBhcmFtIG4gY2h1bmsgc2l6ZSBbMV1cbiAqIEBwYXJhbSBzIGNodW5rIHN0ZXAgW25dXG4gKiBAcmV0dXJucyB4WzAuLm5dIOKnuiB4W3MuLnMrbl0g4qe6IHhbMnMuLjJzK25dIOKnuiAuLi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNodW5rPFQ+KHg6IFRbXSwgbjogbnVtYmVyPTEsIHM6IG51bWJlcj1uKTogVFtdW10ge1xuICBjb25zdCBhOiBUW11bXSA9IFtdO1xuICBpZiAobjwwKSByZXR1cm4gYTtcbiAgcyA9IE1hdGgubWF4KHMsIDEpO1xuICBjb25zdCBJID0geC5sZW5ndGg7XG4gIGZvciAobGV0IGk9MDsgaTxJOyBpKz1zKVxuICAgIGEucHVzaCh4LnNsaWNlKGksIGkrbikpO1xuICByZXR1cm4gYTtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBDT05DQVQvSk9JTlxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEFwcGVuZCB2YWx1ZXMgZnJvbSBhcnJheXMuXG4gKiBAcGFyYW0geHMgYXJyYXlzXG4gKiBAcmV0dXJucyB44oKAIOKnuiB44oKBIOKnuiAuLi4gfCBbeOKCgCwgeOKCgSwgLi4uXSA9IHhzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25jYXQ8VD4oLi4ueHM6IFRbXVtdKTogVFtdIHtcbiAgcmV0dXJuIChbXSBhcyBUW10pLmNvbmNhdCguLi54cyk7XG59XG5cblxuLyoqXG4gKiBBcHBlbmQgdmFsdWVzIGZyb20gYXJyYXlzIVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIHlzIGFycmF5cyB0byBhcHBlbmRcbiAqIEByZXR1cm5zIHggPSB4IOKnuiB54oKAIOKnuiB54oKBIOKnuiAuLi5dIHwgW3nigoAsIHnigoEsIC4uLl0gPSB5c1xuICovXG5leHBvcnQgZnVuY3Rpb24gY29uY2F0JDxUPih4OiBUW10sIC4uLnlzOiBJdGVyYWJsZTxUPltdKTogVFtdIHtcbiAgZm9yIChjb25zdCB5IG9mIHlzKVxuICAgIHgucHVzaCguLi55KTtcbiAgcmV0dXJuIHg7XG59XG5cblxuLyoqXG4gKiBKb2luIHZhbHVlcyB0b2dldGhlciBpbnRvIGEgc3RyaW5nLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSBzZXAgc2VwYXJhdG9yIFssXVxuICogQHJldHVybnMgXCIkXFx7duKCgFxcfSRcXHtzZXBcXH0kXFx7duKCgVxcfS4uLlwiIHwgduG1oiDiiIggeFxuICovXG5leHBvcnQgZnVuY3Rpb24gam9pbjxUPih4OiBUW10sIHNlcDogc3RyaW5nPVwiLFwiKTogc3RyaW5nIHtcbiAgcmV0dXJuIHguam9pbihzZXApO1xufVxuLy8gI2VuZHJlZ2lvblxuXG5cblxuXG4vLyAjcmVnaW9uIFJFQVJSQU5HRVxuLy8gLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBPYnRhaW4gdmFsdWVzIHRoYXQgY3ljbGUgdGhyb3VnaCBhcnJheS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gaSBiZWdpbiDCsWluZGV4IFswXVxuICogQHBhcmFtIG4gbnVtYmVyIG9mIHZhbHVlcyBbfHh8XVxuICovXG5leHBvcnQgZnVuY3Rpb24gY3ljbGU8VD4oeDogVFtdLCBpOiBudW1iZXI9MCwgbjogbnVtYmVyPXgubGVuZ3RoKTogVFtdIHtcbiAgY29uc3QgWCA9IHgubGVuZ3RoO1xuICBpZiAobjw9MCB8fCBYPT09MCkgcmV0dXJuIFtdO1xuICBpID0gbW9kKGksIFgpO1xuICBjb25zdCBhID0geC5zbGljZShpLCBpK24pO1xuICBuIC09IGEubGVuZ3RoO1xuICBjb25zdCBNID0gTWF0aC5mbG9vcihuL1gpO1xuICBmb3IgKGxldCBtPTA7IG08TTsgKyttKVxuICAgIGNvbmNhdCQoYSwgeCk7XG4gIHJldHVybiBjb25jYXQkKGEsIHguc2xpY2UoMCwgbiAlIFgpKTtcbn1cblxuXG4vKipcbiAqIFJlcGVhdCBhbiBhcnJheSBnaXZlbiB0aW1lcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiB0aW1lcyBbMV1cbiAqIEByZXR1cm5zIHgg4qe6IHgg4qe6IC4uLihuIHRpbWVzKVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVwZWF0PFQ+KHg6IFRbXSwgbjogbnVtYmVyPTEpOiBUW10ge1xuICBjb25zdCBhOiBUW10gPSBbXTtcbiAgZm9yICg7IG4+MDsgLS1uKVxuICAgIGNvbmNhdCQoYSwgeCk7XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogUmV2ZXJzZSB0aGUgdmFsdWVzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEByZXR1cm5zIFt4W3x4fC0xXSwgeFt8eHwtMl0sIC4uLiwgeFsxXSwgeFswXV1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJldmVyc2U8VD4oeDogVFtdKTogVFtdIHtcbiAgcmV0dXJuIHguc2xpY2UoKS5yZXZlcnNlKCk7XG59XG5leHBvcnQge3JldmVyc2UgYXMgdG9SZXZlcnNlZH07XG5cblxuLyoqXG4gKiBSZXZlcnNlIHRoZSB2YWx1ZXMhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcmV0dXJucyB4ID0gW3hbfHh8LTFdLCB4W3x4fC0yXSwgLi4uLCB4WzFdLCB4WzBdXVxuICovXG5leHBvcnQgZnVuY3Rpb24gcmV2ZXJzZSQ8VD4oeDogVFtdKTogVFtdIHtcbiAgcmV0dXJuIHgucmV2ZXJzZSgpO1xufVxuXG5cbi8qKlxuICogUm90YXRlIHZhbHVlcyBpbiBhcnJheS5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gbiByb3RhdGUgYW1vdW50ICgrdmU6IGxlZnQsIC12ZTogcmlnaHQpIFswXVxuICogQHJldHVybnMgeFtuLi5dIOKnuiB4WzAuLm5dXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByb3RhdGU8VD4oeDogVFtdLCBuOiBudW1iZXI9MCk6IFRbXSB7XG4gIG4gPSBtb2QobiwgeC5sZW5ndGgpO1xuICByZXR1cm4gY29uY2F0JCh4LnNsaWNlKG4pLCB4LnNsaWNlKDAsIG4pKTtcbn1cblxuXG4vKipcbiAqIFJvdGF0ZSB2YWx1ZXMgaW4gYXJyYXkhXG4gKiBAcGFyYW0geCBhbiBhcnJheSAodXBkYXRlZCEpXG4gKiBAcGFyYW0gbiByb3RhdGUgYW1vdW50ICgrdmU6IGxlZnQsIC12ZTogcmlnaHQpIFswXVxuICogQHJldHVybnMgeCA9IHhbbi4uXSDip7ogeFswLi5uXVxuICovXG5leHBvcnQgZnVuY3Rpb24gcm90YXRlJDxUPih4OiBUW10sIG46IG51bWJlcj0wKTogVFtdIHtcbiAgbiA9IG1vZChuLCB4Lmxlbmd0aCk7XG4gIGNvbnN0IHkgPSB4LnNsaWNlKDAsIG4pO1xuICB4LmNvcHlXaXRoaW4oMCwgbik7XG4gIHJldHVybiBjb3B5JCh4LCB5LCB4Lmxlbmd0aC1uKTtcbn1cbi8vICNlbmRyZWdpb25cblxuXG5cblxuLy8gI3JlZ2lvbiBTRVQgT1BFUkFUSU9OU1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogRXhhbWluZSBpZiB0aGVyZSBhcmUgbm8gZHVwbGljYXRlIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyDiiIAgduG1oiwgduKxvCDiiIggeCwgaXMgduG1oiDiiaAgduKxvD9cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVW5pcXVlPFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGlmIChmYykgcmV0dXJuIGlzVW5pcXVlRHVhbCh4LCBmYywgZm0pO1xuICBlbHNlICAgIHJldHVybiBpc1VuaXF1ZU1hcCAoeCwgZm0pO1xufVxuXG5mdW5jdGlvbiBpc1VuaXF1ZU1hcDxULCBVPVQ+KHg6IFRbXSwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgcyAgPSBuZXcgU2V0KCk7IGxldCBpID0gLTE7XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgY29uc3QgdyA9IGZtKHYsICsraSwgeCk7XG4gICAgaWYgKHMuaGFzKHcpKSByZXR1cm4gZmFsc2U7XG4gICAgcy5hZGQodyk7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGlzVW5pcXVlRHVhbDxULCBVPVQ+KHg6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IGJvb2xlYW4ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHgxID0gWy4uLnhdLm1hcChmbSk7XG4gIGZvciAoY29uc3Qgd3ggb2YgeDEpIHtcbiAgICBmb3IgKGNvbnN0IHd5IG9mIHgxKVxuICAgICAgaWYgKGZjKHd4LCB3eSk9PT0wKSByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cblxuLyoqXG4gKiBFeGFtaW5lIGlmIGFycmF5cyBoYXZlIG5vIHZhbHVlIGluIGNvbW1vbi5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBhbm90aGVyIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4IOKIqSB5ID0gzqY/XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0Rpc2pvaW50PFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBib29sZWFuIHtcbiAgaWYgKGZjKSByZXR1cm4gaXNEaXNqb2ludER1YWwoeCwgeSwgZmMsIGZtKTtcbiAgZWxzZSAgICByZXR1cm4gaXNEaXNqb2ludE1hcCAoeCwgeSwgZm0pO1xufVxuXG5mdW5jdGlvbiBpc0Rpc2pvaW50TWFwPFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHMgID0gdG9TZXQoeSwgZm0pOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHYgb2YgeCkge1xuICAgIGNvbnN0IHcgPSBmbSh2LCArK2ksIHgpO1xuICAgIGlmIChzLmhhcyh3KSkgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBpc0Rpc2pvaW50RHVhbDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogYm9vbGVhbiB7XG4gIGZjID0gZmMgfHwgQ09NUEFSRTtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgeTEgPSBbLi4ueV0ubWFwKGZtKTsgbGV0IGkgPSAtMTtcbiAgZm9yIChjb25zdCB2eCBvZiB4KSB7XG4gICAgY29uc3Qgd3ggPSBmbSh2eCwgKytpLCB4KTtcbiAgICBmb3IgKGNvbnN0IHd5IG9mIHkxKVxuICAgICAgaWYgKGZjKHd4LCB3eSk9PT0wKSByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59XG5cblxuLyoqXG4gKiBSZW1vdmUgZHVwbGljYXRlIHZhbHVlcy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB24oKALCB24oKBLCAuLi4gfCB24bWiIOKIiCB4OyB24bWiIOKJoCB24rG8IOKIgCBpLCBqXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bmlxdWU8VCwgVT1UPih4OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUW10ge1xuICBpZiAoZmMpIHJldHVybiB1bmlxdWVEdWFsKHgsIGZjLCBmbSk7XG4gIGVsc2UgICAgcmV0dXJuIHVuaXF1ZU1hcCAoeCwgZm0pO1xufVxuXG5mdW5jdGlvbiB1bmlxdWVNYXA8VCwgVT1UPih4OiBUW10sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgcyAgPSBuZXcgU2V0KCk7XG4gIGxldCBpICA9IC0xOyBjb25zdCBhID0gW107XG4gIGZvciAoY29uc3QgdiBvZiB4KSB7XG4gICAgY29uc3QgdyA9IGZtKHYsICsraSwgeCk7XG4gICAgaWYgKHMuaGFzKHcpKSBjb250aW51ZTtcbiAgICBzLmFkZCh3KTsgYS5wdXNoKHYpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5mdW5jdGlvbiB1bmlxdWVEdWFsPFQsIFU9VD4oeDogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBsZXQgaSAgPSAtMTsgY29uc3QgcyA9IFtdLCBhID0gW107XG4gIHg6IGZvciAoY29uc3Qgdnggb2YgeCkge1xuICAgIGNvbnN0IHd4ID0gZm0odngsICsraSwgeCk7XG4gICAgZm9yIChjb25zdCB3cyBvZiBzKVxuICAgICAgaWYgKGZjKHdzLCB3eCk9PT0wKSBjb250aW51ZSB4O1xuICAgIHMucHVzaCh3eCk7IGEucHVzaCh2eCk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gdmFsdWVzIHByZXNlbnQgaW4gYW55IGFycmF5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB5IGFub3RoZXIgYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHgg4oiqIHkgPSBcXHt2IHwgdiDiiIggeCBvciB2IOKIiCB5XFx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bmlvbjxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgcmV0dXJuIHVuaW9uJCh4LnNsaWNlKCksIHksIGZjLCBmbSk7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gdmFsdWVzIHByZXNlbnQgaW4gYW55IGFycmF5IVxuICogQHBhcmFtIHggYW4gYXJyYXkgKHVwZGF0ZWQhKVxuICogQHBhcmFtIHkgYW5vdGhlciBhcnJheVxuICogQHBhcmFtIGZjIGNvbXBhcmUgZnVuY3Rpb24gKGEsIGIpXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2LCBpLCB4KVxuICogQHJldHVybnMgeCA9IHgg4oiqIHkgPSBcXHt2IHwgdiDiiIggeCBvciB2IOKIiCB5XFx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bmlvbiQ8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGlmIChmYykgcmV0dXJuIHVuaW9uRHVhbCQoeCwgeSwgZmMsIGZtKTtcbiAgZWxzZSAgICByZXR1cm4gdW5pb25NYXAkICh4LCB5LCBmbSk7XG59XG5cbmZ1bmN0aW9uIHVuaW9uTWFwJDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHMgID0gdG9TZXQoeCwgZm0pOyBsZXQgaSA9IC0xO1xuICBmb3IgKGNvbnN0IHZ5IG9mIHkpIHtcbiAgICBjb25zdCB3eSA9IGZtKHZ5LCArK2ksIHkpO1xuICAgIGlmICghcy5oYXMod3kpKSB4LnB1c2godnkpO1xuICB9XG4gIHJldHVybiB4O1xufVxuXG5mdW5jdGlvbiB1bmlvbkR1YWwkPFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUW10ge1xuICBmYyA9IGZjIHx8IENPTVBBUkU7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHgxID0geC5tYXAoZm0pOyBsZXQgaSA9IC0xO1xuICB5OiBmb3IgKGNvbnN0IHZ5IG9mIHkpIHtcbiAgICBjb25zdCB3eSA9IGZtKHZ5LCArK2ksIHkpO1xuICAgIGZvciAoY29uc3Qgd3ggb2YgeDEpXG4gICAgICBpZiAoZmMod3gsIHd5KT09PTApIGNvbnRpbnVlIHk7XG4gICAgeC5wdXNoKHZ5KTtcbiAgfVxuICByZXR1cm4geDtcbn1cblxuXG4vKipcbiAqIE9idGFpbiB2YWx1ZXMgcHJlc2VudCBpbiBib3RoIGFycmF5cy5cbiAqIEBwYXJhbSB4IGFuIGFycmF5XG4gKiBAcGFyYW0geSBhbm90aGVyIGFycmF5XG4gKiBAcGFyYW0gZmMgY29tcGFyZSBmdW5jdGlvbiAoYSwgYilcbiAqIEBwYXJhbSBmbSBtYXAgZnVuY3Rpb24gKHYsIGksIHgpXG4gKiBAcmV0dXJucyB4IOKIqSB5ID0gXFx7diB8IHYg4oiIIHgsIHYg4oiIIHlcXH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGludGVyc2VjdGlvbjxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgaWYgKGZjKSByZXR1cm4gaW50ZXJzZWN0aW9uRHVhbCh4LCB5LCBmYywgZm0pO1xuICBlbHNlICAgIHJldHVybiBpbnRlcnNlY3Rpb25NYXAgKHgsIHksIGZtKTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uTWFwPFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgZm0gPSBmbSB8fCBJREVOVElUWTtcbiAgY29uc3QgcyAgPSB0b1NldCh5LCBmbSk7XG4gIGxldCBpICA9IC0xOyBjb25zdCBhID0gW107XG4gIGZvciAoY29uc3Qgdnggb2YgeCkge1xuICAgIGNvbnN0IHd4ID0gZm0odngsICsraSwgeCk7XG4gICAgaWYgKHMuaGFzKHd4KSkgYS5wdXNoKHZ4KTtcbiAgfVxuICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gaW50ZXJzZWN0aW9uRHVhbDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB5MSA9IFsuLi55XS5tYXAoZm0pO1xuICBsZXQgaSAgPSAtMTsgY29uc3QgYSA9IFtdO1xuICB4OiBmb3IgKGNvbnN0IHZ4IG9mIHgpIHtcbiAgICBjb25zdCB3eCA9IGZtKHZ4LCArK2ksIHgpO1xuICAgIGZvciAoY29uc3Qgd3kgb2YgeTEpXG4gICAgICBpZiAoZmMod3gsIHd5KT09PTApIHsgYS5wdXNoKHZ4KTsgY29udGludWUgeDsgfVxuICB9XG4gIHJldHVybiBhO1xufVxuXG5cbi8qKlxuICogT2J0YWluIHZhbHVlcyBub3QgcHJlc2VudCBpbiBhbm90aGVyIGFycmF5LlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB5IGFub3RoZXIgYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHggLSB5ID0gXFx7diB8IHYg4oiIIHgsIHYg4oiJIHlcXH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRpZmZlcmVuY2U8VCwgVT1UPih4OiBUW10sIHk6IFRbXSwgZmM6IENvbXBhcmVGdW5jdGlvbjxUfFU+IHwgbnVsbD1udWxsLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGlmIChmYykgcmV0dXJuIGRpZmZlcmVuY2VEdWFsKHgsIHksIGZjLCBmbSk7XG4gIGVsc2UgICAgcmV0dXJuIGRpZmZlcmVuY2VNYXAgKHgsIHksIGZtKTtcbn1cblxuZnVuY3Rpb24gZGlmZmVyZW5jZU1hcDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmbTogTWFwRnVuY3Rpb248VCwgVHxVPiB8IG51bGw9bnVsbCk6IFRbXSB7XG4gIGZtID0gZm0gfHwgSURFTlRJVFk7XG4gIGNvbnN0IHMgID0gdG9TZXQoeSwgZm0pO1xuICBsZXQgaSAgPSAtMTsgY29uc3QgYSA9IFtdO1xuICBmb3IgKGNvbnN0IHZ4IG9mIHgpIHtcbiAgICBjb25zdCB3eCA9IGZtKHZ4LCArK2ksIHgpO1xuICAgIGlmICghcy5oYXMod3gpKSBhLnB1c2godngpO1xuICB9XG4gIHJldHVybiBhO1xufVxuXG5mdW5jdGlvbiBkaWZmZXJlbmNlRHVhbDxULCBVPVQ+KHg6IFRbXSwgeTogVFtdLCBmYzogQ29tcGFyZUZ1bmN0aW9uPFR8VT4gfCBudWxsPW51bGwsIGZtOiBNYXBGdW5jdGlvbjxULCBUfFU+IHwgbnVsbD1udWxsKTogVFtdIHtcbiAgZmMgPSBmYyB8fCBDT01QQVJFO1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCB5MSA9IFsuLi55XS5tYXAoZm0pO1xuICBsZXQgaSAgPSAtMTsgY29uc3QgYSAgPSBbXTtcbiAgeDogZm9yIChjb25zdCB2eCBvZiB4KSB7XG4gICAgY29uc3Qgd3ggPSBmbSh2eCwgKytpLCB4KTtcbiAgICBmb3IgKGNvbnN0IHd5IG9mIHkxKVxuICAgICAgaWYgKGZjKHd4LCB3eSk9PT0wKSBjb250aW51ZSB4O1xuICAgIGEucHVzaCh2eCk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cblxuLyoqXG4gKiBPYnRhaW4gdmFsdWVzIG5vdCBwcmVzZW50IGluIGJvdGggYXJyYXlzLlxuICogQHBhcmFtIHggYW4gYXJyYXlcbiAqIEBwYXJhbSB5IGFub3RoZXIgYXJyYXlcbiAqIEBwYXJhbSBmYyBjb21wYXJlIGZ1bmN0aW9uIChhLCBiKVxuICogQHBhcmFtIGZtIG1hcCBmdW5jdGlvbiAodiwgaSwgeClcbiAqIEByZXR1cm5zIHgteSDiiKogeS14XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzeW1tZXRyaWNEaWZmZXJlbmNlPFQsIFU9VD4oeDogVFtdLCB5OiBUW10sIGZjOiBDb21wYXJlRnVuY3Rpb248VHxVPiB8IG51bGw9bnVsbCwgZm06IE1hcEZ1bmN0aW9uPFQsIFR8VT4gfCBudWxsPW51bGwpOiBUW10ge1xuICBjb25zdCB4MCA9IGZyb21JdGVyYWJsZSQoeCk7XG4gIGNvbnN0IHkwID0gZnJvbUl0ZXJhYmxlJCh5KTtcbiAgY29uc3QgYXggPSBkaWZmZXJlbmNlKHgwLCB5MCwgZmMsIGZtKTtcbiAgY29uc3QgYXkgPSBkaWZmZXJlbmNlKHkwLCB4MCwgZmMsIGZtKTtcbiAgcmV0dXJuIGNvbmNhdCQoYXgsIGF5KTtcbn1cblxuXG4vKipcbiAqIE9idGFpbiBjYXJ0ZXNpYW4gcHJvZHVjdCBvZiBhcnJheXMuXG4gKiBAcGFyYW0geHMgYXJyYXlzXG4gKiBAcGFyYW0gZm0gbWFwIGZ1bmN0aW9uICh2cywgaSlcbiAqIEByZXR1cm5zIHjigoAgw5cgeOKCgSDDlyAuLi4gPSBcXHtbduKCgCwgduKCgSwgLi4uXSB8IHbigoAg4oiIIHjigoAsIHbigoEg4oiIIHjigoEsIC4uLl0gXFx9XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYXJ0ZXNpYW5Qcm9kdWN0PFQsIFU9VD4oeHM6IFRbXVtdLCBmbTogTWFwRnVuY3Rpb248VFtdLCBUW118VT4gfCBudWxsPW51bGwpOiAoVFtdfFUpW10ge1xuICBmbSA9IGZtIHx8IElERU5USVRZO1xuICBjb25zdCBYUyA9IHhzLmxlbmd0aDtcbiAgY29uc3QgYTogKFRbXXxVKVtdID0gW107XG4gIGlmIChYUz09PTApIHJldHVybiBhO1xuICBjb25zdCBpcyA9IG5ldyBBcnJheShYUykuZmlsbCgwKTtcbiAgY29uc3QgbHMgPSB4cy5tYXAoeCA9PiB4Lmxlbmd0aCk7XG4gIGlmIChscy5zb21lKGwgPT4gbD09PTApKSByZXR1cm4gYTtcbiAgZm9yIChsZXQgaT0wOzsgKytpKSB7XG4gICAgY29uc3QgdnM6IFRbXSA9IFtdO1xuICAgIGZvciAobGV0IGo9MDsgajxYUzsgKytqKVxuICAgICAgdnMucHVzaCh4c1tqXVtpc1tqXV0pO1xuICAgIGEucHVzaChmbSh2cywgaSwgbnVsbCkpO1xuICAgIGxldCByID0gWFMtMTtcbiAgICBmb3IgKDsgcj49MDsgLS1yKSB7XG4gICAgICBpZiAoKytpc1tyXTxsc1tyXSkgYnJlYWs7XG4gICAgICBpc1tyXSA9IDA7XG4gICAgfVxuICAgIGlmIChyPDApIGJyZWFrO1xuICB9XG4gIHJldHVybiBhO1xufVxuLy8gI2VuZHJlZ2lvblxuLy8gI2VuZHJlZ2lvblxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGdCQUFnQjtBQUNoQixnQkFBZ0I7QUFFaEIsbUVBQW1FLEdBNkZuRSxhQUFhO0FBS2Isa0JBQWtCO0FBQ2xCLGtCQUFrQjtBQUVsQixrQkFBa0I7QUFDbEIsa0JBQWtCO0FBRWxCLG1DQUFtQyxHQUNuQyxTQUFTLFNBQVksQ0FBSTtFQUN2QixPQUFPO0FBQ1Q7QUFHQSx3QkFBd0IsR0FDeEIsU0FBUyxRQUFXLENBQUksRUFBRSxDQUFJO0VBQzVCLE9BQU8sSUFBRSxJQUFHLENBQUMsSUFBSyxJQUFFLElBQUcsSUFBSTtBQUM3QjtBQUdBLGlFQUFpRSxHQUNqRSxTQUFTLElBQUksQ0FBUyxFQUFFLENBQVM7RUFDL0IsT0FBTyxJQUFJLElBQUksS0FBSyxLQUFLLENBQUMsSUFBRTtBQUM5QjtBQUdBLGdDQUFnQyxHQUNoQyxTQUFTLE1BQWMsQ0FBTSxFQUFFLEtBQTZCLElBQUk7RUFDOUQsSUFBSSxDQUFDLElBQUksT0FBTyxJQUFJLElBQUk7RUFDeEIsTUFBTSxJQUFJLElB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