"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.forEach = forEach;
exports.reduce = reduce;
exports.rotate = rotate;
exports.at = at;
exports.removeAt = removeAt;
exports.remove = remove;
exports.pull = pull;
exports.push = push;
exports.insert = insert;
exports.unshift = unshift;
exports.lastIndex = lastIndex;
exports.last = last;
exports.butLast = butLast;
exports.pop = pop;
exports.rangeArray = rangeArray;
exports.repeatArray = repeatArray;
exports.matchAll = matchAll;
exports.matchAllExc = matchAllExc;
exports._matchAllExc = _matchAllExc;
exports.reorder = reorder;
exports.sum = sum;
exports.min = min;
exports.max = max;
exports.shuffleInplace = shuffleInplace;
exports.shuffle = shuffle;
exports.permutations = permutations;
function forEach(array, callback) {
    array.forEach(callback);
}
function reduce(array, acc, callback) {
    return array.reduce(callback, acc);
}
// https://stackoverflow.com/questions/1985260/javascript-array-rotate
function rotate(array, count) {
    const len = array.length >>> 0; // convert to uint
    count = count >> 0; // convert to int
    // convert count to value in range [0, len)
    count = ((count % len) + len) % len;
    array.push(...array.splice(0, count));
    return array;
}
function at(array, index) {
    return array[index];
}
function removeAt(array, index) {
    array.splice(index, 1);
}
function remove(array, element) {
    const index = array.indexOf(element);
    removeAt(array, index);
}
function pull(array, element) {
    const index = array.indexOf(element);
    removeAt(array, index);
}
function push(array, element) {
    array.push(element);
}
function insert(array, element, at) {
    array.splice(at, 0, element);
    return array;
}
function unshift(array, ...elements) {
    return array.unshift(...elements);
}
function lastIndex(array) {
    const _lastIndex = array.length - 1;
    return _lastIndex;
}
function last(array, offset = 0) {
    const _lastIndex = lastIndex(array);
    const _last = array[_lastIndex + offset];
    return _last;
}
function butLast(array) {
    const _butLast = array.slice(0, -1);
    return _butLast;
}
function pop(array) {
    const l = array.length;
    const last = array[l - 1];
    const rest = array.slice(0, l - 1);
    return [last, rest];
}
function rangeArray(n) {
    const array = [];
    for (let i = 0; i < n; i++) {
        array.push(i);
    }
    return array;
}
function repeatArray(n, value) {
    const array = [];
    for (let i = 0; i < n; i++) {
        array.push(value);
    }
    return array;
}
function matchAll(a, b, match) {
    const all = [];
    for (let i = 0; i < a.length; i++) {
        const ai = a[i];
        for (let j = 0; j < b.length; j++) {
            const bi = b[j];
            if (match(ai, bi)) {
                all.push([i, j]);
            }
        }
    }
    return all;
}
function indexSet(a) {
    return new Set(rangeArray(a.length));
}
// exclusive
function matchAllExc(a, b, match) {
    return _matchAllExc(a, b, indexSet(a), indexSet(b), [], match);
}
function _matchAllExc(a, b, _a, _b, _all, match) {
    let all = [];
    for (let i of _a) {
        const ai = a[i];
        for (let j of _b) {
            const bi = b[j];
            if (match(ai, bi)) {
                const __a = new Set(_a);
                const __b = new Set(_b);
                __a.delete(i);
                __b.delete(j);
                const other = _matchAllExc(a, b, __a, __b, _all, match);
                if (other.length > 0) {
                    for (const x of other) {
                        all.push([[i, j], ...x]);
                    }
                }
                else {
                    all.push([..._all, [i, j]]);
                }
            }
        }
    }
    return all;
}
function reorder(array, element, to) {
    remove(array, element);
    insert(array, element, to);
}
function sum(array) {
    return array.reduce((acc, value) => acc + value, 0);
}
function min(array) {
    return array.reduce((acc, value) => Math.min(acc, value), Infinity);
}
function max(array) {
    return array.reduce((acc, value) => Math.max(acc, value), -Infinity);
}
function shuffleInplace(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        const temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}
function shuffle(array) {
    const shuffledArray = [...array];
    for (let i = shuffledArray.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [shuffledArray[i], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i]];
    }
    return shuffledArray;
}
function* permutations(arr) {
    const a = arr.slice();
    function* generate(n, array) {
        if (n <= 1) {
            yield array.slice();
        }
        else {
            for (let i = 0; i < n - 1; i++) {
                yield* generate(n - 1, array);
                const swapIndex = n % 2 === 0 ? i : 0;
                [array[swapIndex], array[n - 1]] = [array[n - 1], array[swapIndex]];
            }
            yield* generate(n - 1, array);
        }
    }
    yield* generate(a.length, a);
}
//# sourceMappingURL=index.js.map