SOURCE

console.log = function(...args){
  document.writeln(args);  
  document.writeln('<br/>');
}

/**
 * 类似全排列
 *
 * */

function swap(arr, index1, index2) {
    [
        arr[index2], arr[index1]
    ] = [
        arr[index1], arr[index2]
    ];
}

// 两数混合加减乘除
function get2NumsFormula(a, b, isOuter = false) {
    const base = [
        `(${a}-${b})`,
        `(${a}+${b})`,
        `(${a}*${b})`,
        `(${a}/${b})`,

        `(${b}-${a})`,
        // `(${b}+${a})`, // 运算结果相同
        // `(${b}*${a})`, // 运算结果相同
        `(${b}/${a})`,
    ];

    if (!isOuter) {
        base.push(
            `(${b}+${a})`,
        );
    }

    return base;
}

function get3NumsFormula(a, b, c) {
    "use strict"; // arguments分离

    // 3个数全排列 * 符号数量 * 符号数量
    const formulas = [];
    let end = 6;

    // 333
    if (a === b && b === c) {
        end = 1;
    }

    // 数字重复只有3种组合~
    // 233 -> 332 -> 323
    if (a === b || b === c || a === c) {
        end = 3;
    }

    for (let i = 0; i < end; i++) {
        // 123
        if (i === 0) {
            formulas.push(
                `(${a}+${b}+${c})`,
                `(${a}*${b}*${c})`,
            );
        }


        // 231
        if (i === 1) {
            a = arguments[1];
            b = arguments[2];
            c = arguments[0];
        }

        // 312
        if (i === 2) {
            a = arguments[2];
            b = arguments[0];
            c = arguments[1];
        }

        // 另一半
        // 321
        if (i === 3) {
            a = arguments[2];
            b = arguments[1];
            c = arguments[0];
        }

        // 132
        if (i === 4) {
            a = arguments[1];
            b = arguments[0];
            c = arguments[2];
        }


        // 213
        if (i === 5) {
            a = arguments[0];
            b = arguments[2];
            c = arguments[1];
        }

        formulas.push(
            // `(${a}+${b}+${c})`,
            `(${a}+${b}-${c})`,
            // `(${a}+(${b}+${c}))`,
            // `(${a}+(${b}-${c}))`,
            `(${a}+${b}*${c})`,
            `(${a}+${b}/${c})`,
            // `((${a}+${b})*${c})`,
            // `((${a}+${b})/${c})`,

            `(${a}-${b}+${c})`,
            `(${a}-${b}-${c})`,
            // `(${a}-(${b}+${c}))`,
            `(${a}-(${b}-${c}))`,
            `(${a}-${b}*${c})`,
            `(${a}-${b}/${c})`,
            // `((${a}-${b})*${c})`,
            // `((${a}-${b})/${c})`,

            `(${a}*${b}+${c})`,
            `(${a}*${b}-${c})`,
            `(${a}*(${b}+${c}))`,
            `(${a}*(${b}-${c}))`,
            // `(${a}*${b}*${c})`,
            `(${a}*${b}/${c})`,
            // `((${a}*${b})*${c})`,
            // `((${a}*${b})/${c})`,

            `(${a}/${b}+${c})`,
            `(${a}/${b}-${c})`,
            `(${a}/(${b}+${c}))`,
            `(${a}/(${b}-${c}))`,
            `(${a}/${b}*${c})`,
            `(${a}/${b}/${c})`,
            // `((${a}/${b})*${c})`,
            // `((${a}/${b})/${c})`,
        );
    }

    return formulas;
}

function main(arr, sum = 24) {
    let tag = '';

    function permutation(arr, arrIndex) {
        // if (arrIndex === arr.length - 2) {
        //     return get2NumsFormula(arr[arrIndex], arr[arrIndex + 1]);
        // }
        if (arrIndex === arr.length - 3) {
            return get3NumsFormula(arr[arrIndex], arr[arrIndex + 1], arr[arrIndex + 2]);
        }

        let curPermutations = [];
        const headHistoryStore = {};
        for (let i = arrIndex; i < arr.length; i++) {
            swap(arr, arrIndex, i);
            tag = arr.slice(arrIndex).toString();

            if (headHistoryStore[arr[arrIndex]]) {
                swap(arr, arrIndex, i);
                continue;
            } else {
                headHistoryStore[arr[arrIndex]] = 1;
            }

            const childPermutations = permutation(arr, arrIndex + 1);
            childPermutations.forEach(per => {
                curPermutations = curPermutations.concat(get2NumsFormula(per, arr[arrIndex], arrIndex === 0));
            });

            swap(arr, arrIndex, i);
        }

        return curPermutations;
    }

    const permutations = permutation(arr, 0);
    return permutations.filter(per => eval(per) === sum);
}


console.time('test run');
console.log(main([5, 5, 5, 1]));
console.timeEnd('test run');


console.time('test run');
console.log(main([4, 6, 8, 10]));
console.timeEnd('test run');


console.time('test run');
console.log(main([10, 10, 4, 4]));
console.timeEnd('test run');


console.time('test run');
console.log(main([2, 3, 10, 10]));
console.timeEnd('test run');


// TODO 输入数字重复的时候,怎么去重?
// console.log(get3NumsFormula(1, 2, 3).toString());
const result = main([0, 24, 0, 1]);
const result2 = Array.from(new Set(result));
const hasRepeated = result.length !== result2.length;
console.log('是否重复有重复项:', hasRepeated);
console 命令行工具 X clear

                    
>
console