繁体   English   中英

查找所有可能组合成特定数字的JavaScript

[英]Find all possible combinations which make a specific number JavaScript

我的问题是我有一个数字,例如17; 我还有其他三个常数:2,5,7;

我需要找到所有可能的组合,使特定数字为17或任何其他数字;

5 + 5 + 7 = 17 (1 combination)
5 + 5 + 5 + 2 = 17 (2 combinations)
2 + 2 + 2 + 2 + 2 + 7 = 17 (3 combinations)
2 + 2 + 2 + 2 + 2 + 2 + 5 = 17 (4 combinations)

答案是4。我创建了脚本,该脚本可以正确地使用数字17,但是使用较大的数字20或30时会出错。如何使其适用于所有数字?

 const seek = 30; const firstNum = 2; const secondNum = 5; const thirdNum = 7; let combinations = 0; const maxDivisor = Math.round(seek / 2); for (let i = 1; i <= maxDivisor; i += 1) { if (secondNum * i + thirdNum === seek) { combinations++ } else if (secondNum * i + firstNum === seek) { combinations++ } else if (firstNum * i + secondNum === seek) { combinations++ } else if (firstNum * i + thirdNum === seek) { combinations++ } else if (thirdNum * i + firstNum === seek || thirdNum * i + secondNum === 0) { combinations++ } else if (firstNum + secondNum + thirdNum === seek) { combinations++ } else if (firstNum * i === seek || thirdNum * i === seek || secondNum * i === seek) { combinations++ } } console.log(combinations); 

一种简单的解决方案是,首先为每个数字计算最大乘数,然后继续求和所有可能的组合。

 /** LOGIC **/ function getCombinations(inputNumber, pieceNumbers) { const combinations = [] const initial = maxes(inputNumber, pieceNumbers); let divs = initial; const sum = createSum(pieceNumbers); while (!allZeros(divs)) { if (sum(divs) === inputNumber) { combinations.push(divs); } divs = decrement(divs, initial); } return combinations; } /** * returns max multiplier for each number * that is less than input number * ie. for [2, 5] and input 17 * you get [8 (17 / 2); 3 (17 / 5)] */ function maxes(inputNumber, pieceNumbers) { return pieceNumbers.map((num, i) => inputNumber / num | 0 ) } /** * decrements list of numbers till it contains only zeros * if we have divs [2, 0] and initial [2, 5] the result * will be [1, 5] */ function decrement(divs, initial) { const arr = divs.slice(); let i = arr.length; while (i--) { if (arr[i] > 0) { return [...arr.slice(0, i), arr[i] - 1, ...initial.slice(i + 1)]; } } } function allZeros(divs) { return divs.every(div => div === 0); } function createSum(pieceNumbers) { return (divs) => divs.reduce((acc, itm, i) => acc + itm * pieceNumbers[i], 0); } function toPrint(combinations, pieceNumbers) { const printable = combinations.map(nums => nums.map( (n, i) => Array(n).fill(pieceNumbers[i]).join(" + ") ) .filter(x => x) .join(" + ") ).join("\\n"); return printable; } /** VIEW **/ const addPieceEl = document.querySelector(".js-add-piece-number"); const removePieceEl = document.querySelector(".js-remove-piece-number"); const calculateEl = document.querySelector(".js-calculate"); const displayEl = document.querySelector(".js-display-result"); addPieceEl.addEventListener("click", () => { addPieceEl.insertAdjacentHTML("beforebegin", ` <input type="number" class="js-piece-number number" value="7" /> `) }) removePieceEl.addEventListener("click", () => { addPieceEl.previousElementSibling.remove() }) calculateEl.addEventListener("click", () => { const inputNumber = Number(document.querySelector(".js-input-number").value); const pieceNumbers = Array.from(document.querySelectorAll(".js-piece-number")).map(el => Number(el.value)) const combinations = getCombinations(inputNumber, pieceNumbers); const total = `There are ${combinations.length} combinations for ${inputNumber} with ${pieceNumbers.join(", ")}:\\n`; displayEl.textContent = total + toPrint(combinations, pieceNumbers); }); 
 .number { width: 30px; } 
 Input Number: <input type="number" class="js-input-number number" value="17"/> <br/> <br/> Piece Numbers: <input type="number" class="js-piece-number number" value="2"/> <input type="number" class="js-piece-number number" value="5"/> <input type="number" class="js-piece-number number" value="7"/> <button class="js-add-piece-number">+</button> <button class="js-remove-piece-number">-</button> <br/> <br/> <button class="js-calculate">calculate</button> <pre class="js-display-result"/> 

您可以测试所有组合

 const n = 30; console.log('Number to reach: n = ' + n); const k = [7, 5, 2]; console.log('Numbers to use: k = ' + k); console.log('n can be wrote: n = a*k[0] + b*k[1] + c*k[2]'); console.log('Let\\'s found all combinations of [a, b, c]'); let t = []; for (let a = 0; n >= a*k[0]; a++) for (let b = 0; n >= a*k[0] + b*k[1]; b++) for (let c = 0; n >= a*k[0] + b*k[1] + c*k[2]; c++) if (n == a*k[0] + b*k[1] + c*k[2]) t.push([a, b, c]); console.log('Number of combinations: ' + t.length); for (let i = 0; i < t.length; i++) console.log( n + ' = ' + new Array() .concat(new Array(t[i][0]).fill(k[0]).join(' + ')) .concat(new Array(t[i][1]).fill(k[1]).join(' + ')) .concat(new Array(t[i][2]).fill(k[2]).join(' + ')) .filter(e => e.length > 0) .join(' + ') ); 

我假设您只想要2+55+2不是唯一的意义上的唯一解决方案。

使用递归可以创建一个算法,可以解决每个数字和每个常数列表的此问题。

    const seek = 17;
    const numbs = [2,5,7];
    const minNum = Math.min(...numbs);
    let numberOfCombinations = 0;

    seekCombinations(seek, numbs);

    function seekCombinations (toSeek, numbs) {
        for (let i = 0; i < numbs.length; i++) {
            let newToSeek = toSeek - numbs[i];

            if (newToSeek === 0) { //you found a combination

                numberOfCombinations++;

            } else if (newToSeek >= minNum) { //The new number to seek can still form a combination

                //remove numbers from your list of constants that are smaller then then the number that is already in your current combination so you'll only get unique solutions.
                let index = numbs.indexOf(numbs[i]);
                let newNumbs = numbs.slice(index, numbs.length);

                //recursively call seekCombinations
                seekCombinations (newToSeek, newNumbs, currentCombination)
            }
        }
    }

那么问题是什么? 您的脚本有什么问题或怎么做?

以防你错过了它,

数乘以与i犯规解决这个问题。 因为:

30 = 2 + 2 + 5 + 7 + 7 + 7
30 = 2 + 2 + 2 + 5 + 5 + 7 + 7

这3个常数之一的任何数目都可以出现在此处。

这些情况不在您的脚本范围内

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM