自用算法包

个人私用算法包

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         自用算法包
// @namespace    http://tampermonkey.net/
// @version      0.1.6
// @homepage     https://greasyfork.org/zh-CN/users/840688
// @description  个人私用算法包
// @author       Tenfond
// @match        https://*/*
// @match        http://*/*
// @license      AGPL-3.0
// @grant        none
// ==/UserScript==

(function () {
    'use strict';

    // 大数精度位运算
    // const Bit = (function () {
    //     // 反码
    //     function ones_complement(a) {
    //         a = a.split("");
    //         for (let i = 1; i < a.length; i++) {
    //             if (a[0] !== a[i]) {
    //                 a[i] = "1";
    //             } else {
    //                 a[i] = "0";
    //             }
    //         }
    //         return a.join("");
    //     }
    //
    //     return {
    //         // 与
    //         and: function (a, b) {
    //             a = a.toString(2);
    //             b = b.toString(2);
    //             if (a[0] === "-") {
    //                 a = "1" + a.substring(1);
    //                 // 获取补码
    //                 a = (parseInt(ones_complement(a), 2) + 1).toString(2);
    //             } else a = "0" + a;
    //             if (b[0] === "-") {
    //                 b = "1" + b.substring(1);
    //                 // 获取补码
    //                 b = (parseInt(ones_complement(b), 2) + 1).toString(2);
    //             } else b = "0" + b;
    //             if (a.length > b.length) b = b[0] + b.substring(1).padStart(a.length - 1, b[0]);
    //             else a = a[0] + a.substring(1).padStart(b.length - 1, a[0]);
    //             a = a.split("");
    //             b = b.split("");
    //             for (let i = 0; i < a.length; i++) {
    //                 if (a[i] === "1" && b[i] === "1") {
    //                     a[i] = "1";
    //                 } else {
    //                     a[i] = "0";
    //                 }
    //             }
    //             if (a[0] === "1") {
    //                 a = ones_complement((parseInt(a.join(""), 2) - 1).toString(2));
    //                 a = "-" + a.substring(1);
    //             } else {
    //                 a = a.join("");
    //             }
    //             return parseInt(a, 2);
    //         },
    //         // 或
    //         or: function (a, b) {
    //             a = a.toString(2);
    //             b = b.toString(2);
    //             if (a[0] === "-") {
    //                 a = "1" + a.substring(1);
    //                 // 获取补码
    //                 a = (parseInt(ones_complement(a), 2) + 1).toString(2);
    //             } else a = "0" + a;
    //             if (b[0] === "-") {
    //                 b = "1" + b.substring(1);
    //                 // 获取补码
    //                 b = (parseInt(ones_complement(b), 2) + 1).toString(2);
    //             } else b = "0" + b;
    //             if (a.length > b.length) b = b[0] + b.substring(1).padStart(a.length - 1, b[0]);
    //             else a = a[0] + a.substring(1).padStart(b.length - 1, a[0]);
    //             a = a.split("");
    //             b = b.split("");
    //             for (let i = 0; i < a.length; i++) {
    //                 if (a[i] === "1" || b[i] === "1") {
    //                     a[i] = "1";
    //                 } else {
    //                     a[i] = "0";
    //                 }
    //             }
    //             if (a[0] === "1") {
    //                 a = ones_complement((parseInt(a.join(""), 2) - 1).toString(2));
    //                 a = "-" + a.substring(1);
    //             } else {
    //                 a = a.join("");
    //             }
    //             return parseInt(a, 2);
    //         },
    //         // 异或
    //         xor: function (a, b) {
    //             a = a.toString(2);
    //             b = b.toString(2);
    //             if (a[0] === "-") {
    //                 a = "1" + a.substring(1);
    //                 // 获取补码
    //                 a = (parseInt(ones_complement(a), 2) + 1).toString(2);
    //             } else a = "0" + a;
    //             if (b[0] === "-") {
    //                 b = "1" + b.substring(1);
    //                 // 获取补码
    //                 b = (parseInt(ones_complement(b), 2) + 1).toString(2);
    //             } else b = "0" + b;
    //             if (a.length > b.length) b = b[0] + b.substring(1).padStart(a.length - 1, b[0]);
    //             else a = a[0] + a.substring(1).padStart(b.length - 1, a[0]);
    //             a = a.split("");
    //             b = b.split("");
    //             for (let i = 0; i < a.length; i++) {
    //                 if (a[i] !== b[i]) {
    //                     a[i] = "1";
    //                 } else {
    //                     a[i] = "0";
    //                 }
    //             }
    //             if (a[0] === "1") {
    //                 a = ones_complement((parseInt(a.join(""), 2) - 1).toString(2));
    //                 a = "-" + a.substring(1);
    //             } else {
    //                 a = a.join("");
    //             }
    //             return parseInt(a, 2);
    //         },
    //         // 非
    //         not: function (a) {
    //             return -a - 1
    //         },
    //         // 左移
    //         shift: function (a, b) {
    //             a = a.toString(2);
    //             a = a.padEnd(a.length + b, "0");
    //             return parseInt(a, 2);
    //         },
    //         // 右移
    //         move: function (a, b) {
    //             a = a.toString(2);
    //             if (a[0] === "-") {
    //                 a = "1" + a.substring(1);
    //                 // 获取补码
    //                 a = (parseInt(ones_complement(a), 2) + 1).toString(2);
    //             } else a = "0" + a;
    //             b = Math.min(b, a.length - 1);
    //             a = a[0].padEnd(b + 1, a[0]) + a.substring(1, a.length - b);
    //             if (a[0] === "1") {
    //                 // 获取原码
    //                 a = ones_complement((parseInt(a, 2) - 1).toString(2));
    //                 a = "-" + a.substring(1);
    //             }
    //             return parseInt(a, 2);
    //         }
    //     }
    // })();

    // // 正则表达式剔除 注释 和 行首行尾空白符
    // string.replace(new RegExp("\"([^\\\\\"]*(\\\\.)?)*\"|'([^\\\\\']*(\\\\.)?)*'|`([^\\\\`]*(\\\\.)?)*`|\\/{2,}.*?[\r\n]|\\/\\*(\n|.)*?\\*\\/", "g"), function (text) {
    //     return new RegExp("^\\/{2,}").test(text) || new RegExp("^\\/\\*").test(text) ? "" : text;
    //     // 为了防止 代码行末端没有加分号压缩成一行而产生语法无效错误 的发生,这里保留换行符
    // }).replace(new RegExp("\\s*\n\\s+", "g"), "\n").replace(new RegExp("^\\s+|\\s+$"), "")

    // 深拷贝
    Object.clone = function (o, async = false) {
        // 存储已拷贝的旧对象属性的引用,和对应属性在新对象的引用
        const ps = [], properties = [];
        return copy(o);

        // 深拷贝对象
        function copy(o) {
            // 如果没有继承Object就返回原值
            if (!(o instanceof Object)) return o;
            // 如果是Date或RegExp无属性的构造,则新构造一个。(Date.prototype).constructor === Date && (Date.prototype) === (Date.prototype).constructor.prototype,Date.prototype是不能构造的
            else if ((o.constructor === Date || o.constructor === RegExp) && o !== o.constructor.prototype) return new o.constructor(o);
            else {
                // 如果对象是函数类型,就创建代理其内存的代理对象。如果对象继承自Array则创建[],否则就是继承自Object创建{}。
                const object = Object.setPrototypeOf((typeof o === "function") ? (function () {
                    // @formatter:off
                    function Proxy() {return o.apply(this, arguments);}
                    // @formatter:on
                    delete Proxy["name"];
                    delete Proxy["length"];
                    Proxy["prototype"] = c("prototype");
                    return Proxy;
                })() : o instanceof Array ? [] : {}, o);
                const handle = function () {
                    clearTimeout(id);
                    // 函数和Array的部分属性是不可定义的,所以这里获取出来用于检测
                    const names = Object.getOwnPropertyNames(object);
                    // 遍历属性名 重新定义,如果可以定义属性就定义属性
                    for (const p of Object.getOwnPropertyNames(o)) if (names.indexOf(p) === -1) Object.defineProperty(object, p, (function () {
                        const {configurable, ...args} = Object.getOwnPropertyDescriptor(o, p);
                        if (args["value"] !== undefined) args["value"] = c(p);
                        return args;
                    })());
                    // 迭代一个对象的除Symbol以外的可枚举属性,包括继承的可枚举属性
                    // for (const p in o) if (ops.indexOf(p) === -1) object[p] = c(p);
                    // 获取对象Symbol属性 并 重新定义
                    for (const p of Object.getOwnPropertySymbols(o)) Object.defineProperty(object, p, (function () {
                        const {configurable, ...args} = Object.getOwnPropertyDescriptor(o, p);
                        if (args["value"] !== undefined) args["value"] = c(p);
                        return args;
                    })());
                };
                // 是否异步拷贝
                if (async) {
                    var id = setTimeout(handle);
                    return object;
                } else {
                    handle();
                    return object;
                }

                // 深拷贝属性
                function c(p) {
                    // 如果 该属性值没有被定义过,就进行深拷贝并存储这个引用
                    // 如果引用了已拥有的属性内存地址,则让object的p属性也指向指定位置
                    const index = ps.indexOf(o[p]);
                    if (index === -1) {
                        if (async) {
                            const object = copy(o[p]);
                            ps.push(o[p]);
                            properties.push(object);
                            return object;
                        } else {
                            ps.push(o[p]);
                            const object = copy(o[p]);
                            properties.push(object);
                            return object;
                        }
                    } else return properties[index];
                }
            }
        }
    };

    // 双向链表
    window.LinkedList = (function () {
        // 将 多个可迭代对象的对象 转换为链表的节点
        function objectsToNodes(...objects) {
            let next = undefined, prev = undefined, length = 0;
            for (const object of objects) for (const value of object) {
                const node = {value: value, next: undefined, prev: prev};
                if (next !== undefined) {
                    prev.next = node;
                    prev = node;
                } else next = prev = node;
                length++;
            }
            return {next, prev, length};
        }

        // 创建一个在每个实例中存储私有变量的对象
        const internal = Symbol("internal");

        // 创建一个长度位length的双链表
        function LinkedList(length = 0) {
            if (this instanceof LinkedList) {
                Object.defineProperty(this, internal, {
                    // 将多个可迭代对象转换为链表
                    value: {next: undefined, prev: undefined, length: 0},
                    writable: false,
                    enumerable: false
                });
                if (length > 0) {
                    this[internal].next = this[internal].prev = {value: undefined, next: undefined, prev: undefined};
                    this[internal].length = 1;
                    for (let i = 1; i < length; i++) {
                        this[internal].prev.next = {value: undefined, next: undefined, prev: this[internal].prev};
                        this[internal].prev = this[internal].prev.next;
                        this[internal].length++;
                    }
                }
                return this;
            } else return new LinkedList(length);
        }

        //  将多个可迭代对象,转换为链表
        LinkedList.from = function (...objects) {
            const object = Object.setPrototypeOf({}, LinkedList.prototype);
            Object.defineProperty(object, internal, {
                // 将多个可迭代对象转换为链表
                value: objectsToNodes(...objects),
                writable: false,
                enumerable: false
            });
            return object;
        };

        // 将多个值,合成为双链表
        LinkedList.of = function (...values) {
            const object = Object.setPrototypeOf({}, LinkedList.prototype);
            Object.defineProperty(object, internal, {
                // 将参数列表转换为链表
                value: objectsToNodes(values),
                writable: false,
                enumerable: false
            });
            return object;
        };

        // 链表属性 和 迭代器、增删改查 方法
        Object.defineProperties(LinkedList.prototype, {
            length: {
                enumerable: true, get: function () {
                    return this[internal].length;
                }
            }, first: {
                enumerable: true, get: function () {
                    return this[internal].next;
                }
            }, last: {
                get: function () {
                    return this[internal].prev;
                }
            },
            // 定义迭代器,使对象可以被迭代
            [Symbol.iterator]: {
                value: function () {
                    let handle = this[internal];
                    return {
                        next: function () {
                            if (handle.next !== undefined) {
                                handle = handle.next;
                                return {value: handle.value, done: false};
                            } else return {value: undefined, done: true};
                        }
                    }
                },
                enumerable: false
            },
            // 设置类型标签
            [Symbol.toStringTag]: {value: "LinkedList", writable: false, enumerable: false},
            // 返回链表转换得到的数组,改变数组并不会改变链表
            array: {
                enumerable: false, get: function () {
                    let handle = this[internal].next, array = [];
                    while (handle !== undefined) {
                        if (handle.value !== undefined) array.push(handle.value);
                        else array.length++;
                        handle = handle.next;
                    }
                    return array;
                }
            },
            // 从链表末尾添加添加一个或多个元素,并返回数组新的 length
            push: {
                enumerable: false, value: function (...values) {
                    if (values.length === 0) return this[internal].length;
                    const nodes = objectsToNodes(values);
                    if (this[internal].next !== undefined) {
                        this[internal].prev.next = nodes.next;
                        nodes.next.prev = this[internal].prev;
                        this[internal].prev = nodes.prev;
                    } else {
                        this[internal].next = nodes.next;
                        this[internal].prev = nodes.prev;
                    }
                    return this[internal].length += nodes.length;
                }
            },
            // 从链表中移除末尾n个元素并返回移除元素的数组,如果length未定义则移除末尾1个元素并返回移除元素
            pop: {
                enumerable: false, value: function (length = undefined) {
                    if (length === undefined) {
                        if (this[internal].prev !== undefined) {
                            const handle = this[internal].prev;
                            this[internal].prev = handle.prev;
                            if (handle.prev !== undefined) handle.prev.next = undefined;
                            else this[internal].next = undefined;
                            this[internal].length--;
                            return handle.value;
                        } else return undefined;
                    } else {
                        length = Math.floor(length);
                        let array;
                        if (this[internal].prev !== undefined) {
                            if (length > this[internal].length) length = this[internal].length;
                            else if (length <= 0) return [];
                            array = Array(length);
                            let handle = this[internal].prev;
                            for (let i = length - 1; i >= 0; i--) {
                                if (handle.value !== undefined) array[i] = handle.value;
                                handle = handle.prev;
                            }
                            this[internal].prev = handle;
                            if (handle !== undefined) handle.next = undefined;
                            else this[internal].next = undefined;
                            this[internal].length -= array.length;
                        }
                        return array;
                    }
                }
            },
            // 从链表前面添加添加一个或多个元素,并返回数组新的 length
            unshift: {
                enumerable: false, value: function (...values) {
                    if (values.length === 0) return this[internal].length;
                    const nodes = objectsToNodes(values);
                    if (this[internal].next !== undefined) {
                        this[internal].next.prev = nodes.prev;
                        nodes.prev.next = this[internal].next;
                        this[internal].next = nodes.next;
                    } else {
                        this[internal].next = nodes.next;
                        this[internal].prev = nodes.prev;
                    }
                    return this[internal].length += nodes.length;
                }
            },
            // 从链表中移除前面n个元素并返回移除元素的数组,如果length未定义则移除前面1个元素并返回移除元素
            shift: {
                enumerable: false, value: function (length = undefined) {
                    if (length === undefined) {
                        if (this[internal].next !== undefined) {
                            const handle = this[internal].next;
                            this[internal].next = handle.next;
                            if (handle.next !== undefined) handle.next.prev = undefined;
                            else this[internal].prev = undefined;
                            this[internal].length--;
                            return handle.value;
                        } else return undefined;
                    } else {
                        length = Math.floor(length);
                        let array;
                        if (this[internal].next !== undefined) {
                            if (length > this[internal].length) length = this[internal].length;
                            else if (length <= 0) return [];
                            array = Array(length);
                            let handle = this[internal].next;
                            for (let i = 0; i < length; i++) {
                                if (handle.value !== undefined) array[i] = handle.value;
                                handle = handle.next;
                            }
                            this[internal].next = handle;
                            if (handle !== undefined) handle.prev = undefined;
                            else this[internal].prev = undefined;
                            this[internal].length -= array.length;
                        }
                        return array;
                    }
                }
            },
            // 从链表指定位置添加一个或多个元素,并返回数组新的 length
            insert: {
                enumerable: false, value: function (index, ...values) {
                    index = Math.floor(index);
                    const handle = (function () {
                        if (isNaN(index)) return this[internal];
                        else if (index < 0) {
                            index = this[internal].length + index;
                            if (index < 0) return this[internal];
                        } else if (index > this[internal].length) return this[internal].prev;
                        // 就近遍历
                        if (index <= Math.ceil(this[internal].length / 2)) {
                            let handle = this[internal];
                            for (let i = 0; i < index; i++) handle = handle.next;
                            return handle;
                        } else {
                            let handle = this[internal].prev;
                            for (let i = this[internal].length; i > index; i--) handle = handle.prev;
                            return handle;
                        }
                    }).call(this);
                    // 添加值
                    if (values.length > 0) {
                        const nodes = objectsToNodes(values);
                        if (this[internal].next !== undefined) {
                            if (handle !== this[internal].prev) {
                                nodes.prev.next = handle.next;
                                handle.next.prev = nodes.prev;
                            } else this[internal].prev = nodes.prev;
                            handle.next = nodes.next;
                            if (handle !== this[internal]) nodes.next.prev = handle;
                        } else {
                            this[internal].next = nodes.next;
                            this[internal].prev = nodes.prev;
                        }
                        return this[internal].length += nodes.length;
                    }
                }
            },
            // 从链表指定位置截取n个值并在该位置添加值,返回一个Array
            splice: {
                // index(可选)指定了从哪个坐标开始(包含这个坐标)移除和添加内容;如果是负值则表示从数组末位开始的第几位(从 -1 计数,这意味着 -n 是倒数第 n 个元素并且等价于 LinkedList.length-n);如果超出了数组的长度,则从数组末尾开始添加内容;如果负数的绝对值大于数组的长度 或 转换为数字为NaN,则表示开始位置为第 0 位
                // length(可选)表示要移除的数组元素的个数。如果 length 大于 index 之后的元素的总数,则从 index 后面的元素都将被删除(含第 index 位)。如果 length 被省略了,或者它的值大于等于 LinkedList.length-index (也就是说,如果它大于或者等于 index 之后的所有元素的数量),那么 index 之后数组的所有元素都会被删除。如果 length 是 0 或 负数 或 转换为数字为NaN,则不移除元素。这种情况下,至少应添加一个新元素
                // ...values(可选)item1, item2, ... 要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素
                // 返回值 由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组
                enumerable: false, value: function (index = 0, length = Infinity, ...values) {
                    index = Math.floor(index);
                    length = Math.floor(length);
                    if (isNaN(index)) index = 0;
                    else if (index < 0) {
                        index = this[internal].length + index;
                        if (index < 0) index = 0;
                    } else if (index > this[internal].length) index = this[internal].length;
                    const maxDeletionLength = this[internal].length - index;
                    if (length > maxDeletionLength) length = maxDeletionLength;
                    else if (length < 0) length = 0;
                    const array = Array(length);
                    // 就近遍历
                    let handle, flag;
                    if (index <= Math.ceil(this[internal].length / 2)) {
                        handle = this[internal];
                        for (let i = 0; i < index; i++) handle = handle.next;
                        // 记录下标的值
                        flag = handle;
                        for (let i = 0; i < length; i++) {
                            handle = handle.next;
                            if (handle.value !== undefined) array[i] = handle.value;
                        }
                    } else {
                        handle = this[internal].prev;
                        // 在删除前,删除后 的位置
                        length = index + length;
                        for (let i = this[internal].length; i > length; i--) handle = handle.prev
                        // handle停留在删除后的位置,并将flag遍历到删除前的下标的值
                        flag = handle;
                        for (let i = length; i > index; i--) {
                            if (flag.value !== undefined) array[i - index - 1] = flag.value;
                            flag = flag.prev;
                        }
                    }
                    // 移除值
                    if (flag !== handle) {
                        flag.next = handle.next;
                        if (handle.next !== undefined) {
                            if (flag !== this[internal]) handle.next.prev = flag;
                            else handle.next.prev = undefined;
                        } else {
                            if (flag !== this[internal]) this[internal].prev = flag;
                            else this[internal].prev = undefined;
                        }
                        this[internal].length -= array.length;
                    }
                    // 添加值
                    if (values.length > 0) {
                        const nodes = objectsToNodes(values);
                        if (this[internal].next !== undefined) {
                            if (flag !== this[internal].prev) {
                                nodes.prev.next = flag.next;
                                flag.next.prev = nodes.prev;
                            } else this[internal].prev = nodes.prev;
                            flag.next = nodes.next;
                            if (flag !== this[internal]) nodes.next.prev = flag;
                        } else {
                            this[internal].next = nodes.next;
                            this[internal].prev = nodes.prev;
                        }
                        this[internal].length += nodes.length;
                    }
                    return array;
                }
            },
            // 修改指定元素的值,返回修改前的值,若没有修改,则返回undefined;如果index={index:value,...}这样的形式,则返回对应下标修改前的map(object)对象。因为object会自动排序,所以这里不能用array
            set: {
                enumerable: false, value: function (index, value = undefined) {
                    if (value !== undefined && typeof index !== "object") {
                        if (isNaN(index)) return;
                        else if (index < 0) {
                            index = this[internal].length + index;
                            if (index < 0) return;
                        } else if (index > this[internal].length) return;
                        // 就近遍历
                        if (index <= Math.ceil(this[internal].length / 2)) {
                            let handle = this[internal].next;
                            for (let i = 0; i < index; i++) handle = handle.next;
                            const result = handle.value;
                            handle.value = value;
                            return result;
                        } else {
                            let handle = this[internal].prev;
                            for (let i = this[internal].length - 1; i > index; i--) handle = handle.prev;
                            const result = handle.value;
                            handle.value = value;
                            return result;
                        }
                    } else {
                        let i = 0, handle = this[internal].next, j = i, flag = handle;
                        const map = {};
                        for (let k in index) {
                            if (isNaN(k) || k > this[internal].length || k < 0) continue;
                            k = Math.floor(k);
                            if (Math.abs(k - i) > Math.abs(k - j)) {
                                i = j;
                                handle = flag;
                            }
                            if (Math.abs(k - i) <= k && Math.abs(k - i) <= Math.abs(k - this[internal].length)) {
                                if (k > i) for (; i < k; i++) handle = handle.next;
                                else for (; i > k; i--) handle = handle.prev;
                                map[k] = handle.value;
                                handle.value = index[k];
                            } else {
                                // 就近遍历
                                if (k <= Math.ceil(this[internal].length / 2)) {
                                    flag = this[internal].next;
                                    for (j = 0; j < k; j++) flag = flag.next
                                } else {
                                    flag = this[internal].prev;
                                    for (j = this[internal].length - 1; j > k; j--) flag = flag.prev;
                                }
                                map[k] = flag.value;
                                flag.value = index[k];
                            }
                        }
                        return map;
                    }
                }
            },
            // 获取指定下标元素值,如果只输入了一个index,则返回对应index元素值;如果输入多个index,根据输入的下标按顺序返回一个数组,如果指定没找到,则以数组对应位置以空位填充;如果无参数则返回空数组
            get: {
                enumerable: false, value: function (...index) {
                    if (index.length === 1) {
                        index = index[0];
                        if (isNaN(index)) return;
                        else if (index < 0) {
                            index = this[internal].length + index;
                            if (index < 0) return;
                        } else if (index > this[internal].length) return;
                        // 就近遍历、
                        if (index <= Math.ceil(this[internal].length / 2)) {
                            let handle = this[internal].next;
                            for (let i = 0; i < index; i++) handle = handle.next
                            return handle.value;
                        } else {
                            let handle = this[internal].prev;
                            for (let i = this[internal].length - 1; i > index; i--) handle = handle.prev;
                            return handle.value;
                        }
                    } else {
                        let i = 0, handle = this[internal].next, j = i, flag = handle;
                        const array = [];
                        for (let k in index) {
                            if (isNaN(k) || k > this[internal].length || k < 0) {
                                array.length++;
                                continue;
                            }
                            k = Math.floor(k);
                            if (Math.abs(k - i) > Math.abs(k - j)) {
                                i = j;
                                handle = flag;
                            }
                            if (Math.abs(k - i) <= k && Math.abs(k - i) <= Math.abs(k - this[internal].length)) {
                                if (k > i) for (; i < k; i++) handle = handle.next;
                                else for (; i > k; i--) handle = handle.prev;
                                if (handle.value !== undefined) array.push(handle.value);
                                else array.length++;
                            } else {
                                // 就近遍历
                                if (k <= Math.ceil(this[internal].length / 2)) {
                                    flag = this[internal].next;
                                    for (j = 0; j < k; j++) flag = flag.next
                                } else {
                                    flag = this[internal].prev;
                                    for (j = this[internal].length - 1; j > k; j--) flag = flag.prev;
                                }
                                if (flag.value !== undefined) array.push(flag.value);
                                else array.length++;
                            }
                        }
                        return array;
                    }
                }
            },
            // slice() 方法返回一个新的数组对象,这一对象是一个 [index,end) 范围的数组
            slice: {
                enumerable: false, value: function (index, end = this[internal].length) {
                    index = Math.floor(index);
                    end = Math.floor(end);
                    if (isNaN(index)) index = 0;
                    else if (index < 0) {
                        index = this[internal].length + index;
                        if (index < 0) index = 0;
                    } else if (index > this[internal].length) index = this[internal].length;
                    if (end > this[internal].length) end = this[internal].length;
                    else if (end < 0) end = 0;
                    const array = Array(end - index);
                    // 就近遍历
                    let handle;
                    if (index <= Math.ceil(this[internal].length / 2)) {
                        handle = this[internal].next;
                        for (let i = 0; i < index; i++) handle = handle.next;
                        for (let i = index; i < end; i++) {
                            if (handle.value !== undefined) array[i - index] = handle.value;
                            handle = handle.next;
                        }
                    } else {
                        handle = this[internal].prev;
                        for (let i = this[internal].length - 1; i > end; i--) handle = handle.prev;
                        for (let i = end - 1; i >= index; i--) {
                            if (handle.value !== undefined) array[i - index] = handle.value;
                            handle = handle.prev;
                        }
                    }
                    return array;
                }
            },
            // 返回从0开始遍历,第一个指定value的下标
            indexOf: {
                enumerable: false, value: function (value) {
                    let handle = this[internal].next, index = 0;
                    while (handle !== undefined) {
                        if (handle.value === value) return index;
                        handle = handle.next;
                        index++;
                    }
                }
            },
            // 返回从0开始遍历,第一个指定value的下标
            lastIndexOf: {
                enumerable: false, value: function (value) {
                    let handle = this[internal].prev, index = this[internal].length - 1;
                    while (handle !== undefined) {
                        if (handle.value === value) return index;
                        handle = handle.prev;
                        index--;
                    }
                }
            },
            // 将可迭代对象,添加到链表中
            concat: {
                enumerable: false, value: function (...objects) {
                    if (objects.length === 0) return this;
                    const nodes = objectsToNodes(...objects);
                    if (this[internal].next !== undefined) {
                        this[internal].prev.next = nodes.next;
                        nodes.next.prev = this[internal].prev;
                        this[internal].prev = nodes.prev;
                    } else {
                        this[internal].next = nodes.next;
                        this[internal].prev = nodes.prev;
                    }
                    this[internal].length += nodes.length;
                    return this;
                }
            },
            // 将每个元素toString并以指定分隔符连接成字符串
            join: {
                enumerable: false, value: function (separator = ",") {
                    if (this[internal].length > 0) {
                        let result = str(this[internal].next.value), handle = this[internal].next.next;
                        while (handle !== undefined) {
                            result += separator + str(handle.value);
                            handle = handle.next;
                        }
                        return result;

                        function str(o) {
                            if (o !== undefined && o !== null) return o.toString();
                            else return "";
                        }
                    } else return "";
                }
            }
        });
        return LinkedList;
    })();

    /**
     * 梅森旋转算法中用到的变量如下所示:
     * w:长度 生成的随机数的二进制长度
     * n:寄存器长度 参与旋转的随机数个数(旋转的深度)
     * m:周期参数,用作第三阶段的偏移量 旋转算法参与旋转的中间项
     * r:低位掩码/低位要提取的位数 内存界限值 2 的 r 次方 - 1 x⃗ (u)kx→k(u) 和 x⃗ (l)k+1x→k+1(l) 的切分位置
     * a:旋转矩阵的参数 旋转算法异或基数 矩阵 AA 的最后一行
     * f:初始化梅森旋转链所需参数 旋转链异或值膨化量
     * u,s,t,l: 整数参数,移位运算的移动距离
     * d,b,c: 比特遮罩
     * s,t:TGFSR的位移量
     * b,c:TGFSR的掩码
     * u,d,l:额外梅森旋转所需的掩码和位移量
     */
    window.MT = (function () {
        // 新方案定义私有变量。修复部分浏览器不支持 # 定义private私有变量
        const internal = Symbol("internal");

        // 旋转算法处理旋转链
        function generate() {
            for (let i = 0n; i < this[internal].n; i++) {
                const lower_mask = -(1n << this[internal].r);
                const upper_mask = ~lower_mask;
                const y = (this[internal].list[i] & upper_mask) + (this[internal].list[(i + 1n) % this[internal].n] & lower_mask);
                let yA = y >> 1n;
                if ((y % 2n) !== 0n) {
                    yA = yA ^ this[internal].a;
                }
                this[internal].list[i] = this[internal].list[(i + this[internal].m) % this[internal].n] ^ yA;
            }
        }

        function MT(seed = Date.now(), bit = 32) {
            if (this instanceof MT) {
                const args = {
                    // MT19937-32的参数列表如下:
                    32: {
                        n: 624n, m: 397n, r: 31n,
                        a: 0x9908B0DFn, f: 1812433253n,
                        u: 11n, d: 0xFFFFFFFFn,
                        s: 7n, b: 0x9D2C5680n,
                        t: 15n, c: 0xEFC60000n,
                        l: 18n
                    },
                    // MT19937-64的参数列表如下:
                    64: {
                        n: 312n, m: 156n, r: 31n,
                        a: 0xB5026F5AA96619E9n, f: 6364136223846793005n,
                        u: 29n, d: 0x5555555555555555n,
                        s: 17n, b: 0x71D67FFFEDA60000n,
                        t: 37n, c: 0xFFF7EEE000000000n,
                        l: 43n
                    }
                };
                if (typeof args[bit] === "undefined") throw new Error("未定义" + bit.toString() + "bit的参数");
                Object.defineProperty(this, internal, {
                    value: {
                        w: BigInt(bit), n: args[bit].n, m: args[bit].m, r: args[bit].r,
                        a: args[bit].a,
                        u: args[bit].u, d: args[bit].d,
                        s: args[bit].s, b: args[bit].b,
                        t: args[bit].t, c: args[bit].c,
                        l: args[bit].l,
                        index: 0n, list: [BigInt(seed)]
                    },
                    writable: false,
                    enumerable: false
                });
                // 对数组其他元素进行初始化
                for (let i = 1n; i < this[internal].n; i++) {
                    this[internal].list[i] = (args[bit].f * (this[internal].list[i - 1n] ^ (this[internal].list[i - 1n] >> (this[internal].w - 2n))) + i & (1n << this[internal].w) - 1n);
                }
                return this;
            } else return new MT(seed, bit);
        }

        Object.defineProperties(MT.prototype, {
            // 获取随机数
            next: {
                enumerable: false, value: function () {
                    if (this[internal].index === 0n) generate.call(this);
                    let y = this[internal].list[this[internal].index];
                    y = (y ^ ((y >> this[internal].u) & this[internal].d));
                    y = (y ^ ((y << this[internal].s) & this[internal].b));
                    y = (y ^ ((y << this[internal].s) & this[internal].b));
                    y = (y ^ ((y << this[internal].t) & this[internal].c));
                    y = (y ^ (y >> this[internal].l));
                    this[internal].index = (this[internal].index + 1n) % this[internal].n;
                    if (this[internal].w <= 53n) y = parseInt(y.toString());
                    return y;
                }
            }
        });

        return MT;
    })();
// 未经许可禁止抄袭算法,可以私用。
    window.Key = (function () {
        // 定义private私有变量
        const internal = Symbol("internal");

        // 自定义加密算法,以防数据包被破解。
        function Key(pwd) {
            if (this instanceof Key) {
                // num,密码偏移量
                // key,排列长度偏移量
                // charCode,防止内存频繁运动,定义在外部
                let key = 7n;
                if (typeof pwd === "string") {
                    for (let i = 0; i < pwd.length; i++) {
                        key = key * 31n + BigInt(pwd[i].charCodeAt(0));
                    }
                    key = key & 0xFFFFFFFFFFFFn;
                } else if ((typeof pwd).match(new RegExp("(number|'bigint')"))) {
                    // 如果密码是数值型就使用此方法作为 密码偏移量 和 排列长度偏移量=
                    key = (key * 31n + BigInt(Math.round(pwd))) & 0xFFFFFFFFFFFFn;
                } else {
                    // 如果类型不匹配就直接提出错误
                    console.error("Unsupported type '" + (typeof pwd) + "'. It only supports 'string' 'number' 'bigint'.");
                }
                // 让排列长度偏移量取第一个数字。加上密码转换成字符字符串的方式
                Object.defineProperty(this, internal, {
                    value: {pwd: key.toString(36)},
                    writable: false,
                    enumerable: false
                });
                return this;
            } else return new Key(pwd);
        }

        Object.defineProperties(Key.prototype, {
            encrypt: {
                enumerable: false, value: function (string, ...strings) {
                    function resolve(string) {
                        if (typeof string === "string" && string.length > 0) {
                            string = string.split("");
                            // 加密种子。
                            const MTSeed = new MT(string.length + parseInt(this[internal].pwd, 36));
                            let result = "";
                            // 打乱顺序并加密
                            for (let i = string.length; i > 0; i--) {
                                const rand = MTSeed.next();   // rand[0,2^32-1]
                                const k = string.splice(rand % i, 1)[0].charCodeAt(0) + rand;
                                result += rand % 2 === 0 ?
                                    String.fromCharCode(Math.floor(k / 0x10000)) + String.fromCharCode(Math.floor(k % 0x10000)) :
                                    String.fromCharCode(Math.floor(k % 0x10000)) + String.fromCharCode(Math.floor(k / 0x10000));
                            }
                            // 返回加密结果
                            return result;
                        } else if (string.constructor.name === "Array") {
                            for (let i = 0; i < string.length; i++) {
                                string[i] = resolve.call(this, string[i]);
                            }
                            return string;
                        } else {
                            // 如果加密字符串不存在就返回string
                            return string;
                        }
                    }

                    if (strings.length === 0) {
                        return resolve.call(this, string);
                    } else {
                        return resolve.call(this, [string].concat(strings));
                    }
                }
            },
            decrypt: {
                enumerable: false, value: function (string, ...strings) {
                    function resolve(string) {
                        if (typeof string === "string" && string.length > 0) {
                            // 加密种子。
                            const MTSeed = new MT(string.length / 2 + parseInt(this[internal].pwd, 36));
                            // 解密并恢复顺序
                            const result = [], map = [];
                            for (let i = 0; i < string.length; i += 2) {
                                const rand = MTSeed.next();   // rand[0,2^32-1]
                                let k = string.substring(i, i + 2);
                                k = rand % 2 === 0 ?
                                    k.charCodeAt(0) * 0x10000 + k.charCodeAt(1) :
                                    k.charCodeAt(1) * 0x10000 + k.charCodeAt(0);
                                map.push([rand % ((string.length - i) / 2), String.fromCharCode(k - rand)]);
                            }
                            for (const item of map.reverse()) result.splice(item[0], 0, item[1]);
                            // 返回加密结果
                            return result.join("");
                        } else if (string.constructor.name === "Array") {
                            for (let i = 0; i < string.length; i++) {
                                string[i] = resolve.call(this, string[i]);
                            }
                            return string;
                        } else {
                            // 如果解密字符串不存在就返回string
                            return string;
                        }
                    }

                    if (strings.length === 0) {
                        return resolve.call(this, string);
                    } else {
                        return resolve.call(this, [string].concat(strings));
                    }
                }
            }
        });

        const KEY = new Key("Tenfond");
        Object.defineProperty(Key, "encrypt", {
            value: function () {
                return KEY.encrypt.apply(KEY, arguments);
            },
            writable: false,
            enumerable: false,
            configurable: false
        });
        Object.defineProperty(Key, "decrypt", {
            value: function () {
                return KEY.decrypt.apply(KEY, arguments);
            },
            writable: false,
            enumerable: false,
            configurable: false
        });
        return Key;
    })();
})();