我正试图找到与数字1-9相等的各种可能性。这个功能可以产生预期的效果,但也有其他我没想过的结果。其他结果加起来为100,但没有这些数字,比如省略3或6.为什么包含这些其他结果?
var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var signs = ["+", "-", "N"];
var results = [];
find100("1");
function find100(expr) {
if (eval(expr.replace(/N/g, "")) === 100) {
results.push(expr);
} else {
for (var i = eval(expr.substring(expr.length - 1, expr.length)) + 1; i <=
nums.length; i++) {
signs.forEach(function(sign) {
var expr2 = expr;
find100(expr2 += sign + i);
});
}
}
}
期望的输出:
1+2+3-4+5+6+78+9,
1+2+34-5+67-8+9,
1+23-4+5+6+78-9,
1+23-4+56+7+8+9,
12+3+4+5-6-7+89,
12+3-4+5+67+8+9,
12-3-4+5-6+7+89,
123+4-5+67-89,
123+45-67+8-9,
123-4-5-6-7+8-9,
123-45-67+89
答案 0 :(得分:2)
它会添加不需要的结果,因为您的第一个循环遍历每个剩余数字并添加任意结果,评估为100,即使它已跳过一个数字也是如此。如果方法找到一个数字的解决方案,它会将解决方案添加到results
- 这是正确的,但是如果它找不到解决方案,它仍会移动到下一个数字。这是跳过的数字的来源。如果没有数字的解决方案,它应该没有继续下一个数字。
至于如何修复它,这是一个不同的问题(但为什么不......)
这里的区别在于,如果任何数字存在使用所有剩余数字的表达式,则只能获得结果。
var results = [];
var operations = [ "+", "-", "" ];
var expected = 100;
var limit = 10;
function findExpression(expr, next) {
if (next === limit) {
eval(expr) === expected && results.push(expr);
} else {
operations.forEach(function(operation) {
findExpression(expr + operation + next, next + 1);
});
}
}
$(document).ready(function() {
findExpression("1", 2);
for(var i=0; i<results.length; i++) {
$("#foo").append(results[i]+"<br />");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
<body>
<div id="foo"></div>
</body>
答案 1 :(得分:1)
跳过某些数字的原因是在这个循环中:
for (var i = eval(expr.substring(expr.length - 1, expr.length)) + 1; i <=
nums.length; i++) {
在第二次迭代中,它将递增表达式中的最后一位数,这将在连续递归中产生间隙。简而言之,那个循环不应该存在。
我建议不使用eval
的解决方案,不是因为它会有某种危险,而是因为它会导致重大的性能损失。
相反,您可以将数值变量更新为表达式所代表的内容。事实上,我建议使用两个这样的变量,一个用于前一个术语的总和,另一个用于最后一个术语,因为那个变量可能仍然需要用更多的数字进行扩展。
为了促进符号影响表达式的不同方式,我已经为每个符号定义了一个函数:它采用上面提到的数值,也是最后一个数字,并返回更新的值。
这是一个使用该想法的工作片段(ES6语法),您会注意到性能的显着改善:
function find100(digits, signs) {
const loop = (expr, i, [sum, value]) =>
// Not yet all digits used?
i < digits.length ?
// Apply each of the signs in turn:
Object.keys(signs).reduce( (results, sign) =>
// Recurse, passing on the modified expression, the sum of the
// preceding terms, and the value of the last term. As '+' is
// not any different than '' before the first digit, skip '+':
sign != '+' || i ?
results.concat(loop(expr+sign+digits[i], i+1,
signs[sign](sum, value, digits[i]))) :
results,
[] ) :
// All digits were used. Did it match?
sum+value == 100 ? [expr] : [];
// Start recursion
return loop('', 0, [0, 0]);
}
var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// define how each sign should modify the expression value:
var signs = {
'+': (sum, value, digit) => [sum+value, digit],
'-': (sum, value, digit) => [sum+value, -digit],
'' : (sum, value, digit) => [sum, value*10 + (value<0 ? -digit : digit)]
};
var results = find100(nums, signs);
console.log(results);
请注意,这也会输出以下表达式:
-1+2-3+4+5+6+78+9
这是因为代码也尝试在第一个数字之前的符号。我认为这也包含在输出中是相关的。