其他人指出了未声明变量的相当简单的问题。
但即使在修复之后,仍然存在三个逻辑错误。您没有在循环内使用循环变量i。虽然有时这没问题,但它不在这里。您需要它作为simplex 的参数。其次,你的循环边界停止了。您想要上一列的 t 条目,但您通过测试 i < t 停止使用 t - 1st 条目。最后,您以1 开始您的积累(n)。总和应该以0 开始累积。修复这些,我们有一个看起来像这样的工作函数:
const simplex = function(s, t) {
if (s == 1) {
return t
} else {
var n = 0;
for (let i = 1; i <= t; i++){
n += simplex(s - 1, i)
}
return n
}
}
添加一些日志语句来显示流程,我们可以得到:
const simplex = function (s, t, d = 0) {
console.log('| '.repeat(d) + `simplex (${s}, ${t})`)
if (s == 1) {
console.log('| '.repeat(d) + `\`+-> ${t}`)
return t
} else {
var n = 0;
for (let i = 1; i <= t; i++){
n += simplex (s - 1, i, d + 1)
}
console.log('| '.repeat(d) + `\`+-> ${n}`)
return n
}
}
simplex (3, 3) //=> 10
.as-console-wrapper {max-height: 100% !important; top: 0}
simplex (3, 3)
| simplex (2, 1)
| | simplex (1, 1)
| | `+-> 1
| `+-> 1
| simplex (2, 2)
| | simplex (1, 1)
| | `+-> 1
| | simplex (1, 2)
| | `+-> 2
| `+-> 3
| simplex (2, 3)
| | simplex (1, 1)
| | `+-> 1
| | simplex (1, 2)
| | `+-> 2
| | simplex (1, 3)
| | `+-> 3
| `+-> 6
`+-> 10
但我相信这个功能可以在很多方面进行简化。有一些简单的事情,比如将else 块移到根,并使用箭头函数代替函数表达式。在我看来,更重要的是使用像 sum 这样的辅助函数来汇总多个值,而不是在这个函数中包含该逻辑。通过还包括countTo,它只返回第一个n 计数,我们可以使用map,使代码更具声明性。所以我可能更喜欢这样的版本:
const countTo = (n) => n < 1 ? [] : [...countTo (n - 1), n]
const sum = (xs) => xs .reduce ((a, b) => a + b, 0)
const simplex = (s) => (t) =>
s == 1
? t
: sum (countTo (t) .map (simplex (s - 1)))
console .log (simplex (3) (3))
此版本还对 API 进行了一项更改。这个函数不是采用单纯形数和项并返回值,而是采用单纯形数并返回一个 function,该函数接受项并返回值。这意味着将其称为simplex (s) (t) 而不是simplex (s, t)。做到这一点并不难,而且有很多好处。但是将其转换为其他格式很容易,只增加了非常小的实现复杂性。
更新
我忘了提到我的第一种方法,即把单纯形数看作是直接进入帕斯卡三角的索引。帕斯卡三角形包含二项式系数,可以使用简单的递归choose (n, k) = choose (n, k - 1) + choose (n - 1, k - 1) 计算,并带有一些简单的基本情况。
使用它,simplex (s, t) 就是choose (s + t - 1, t)。它可能看起来像这样:
const choose = (n, k) =>
k == 0
? 1
: n == 0
? 0
: choose (n - 1, k) + choose (n - 1, k - 1)
// Ex: choose (7, 3) //=> 35
console .log ('Pascal Triangle:\n');
console .log (
Array .from (
{length: 9},
(_, n) => Array .from ({length: n + 1}, (_, r) => choose (n, r))
).map (
r => r .map (n => `${n}`.padStart(2, ' ')) .join (' ')
) .join ('\n') + '\n ...'
)
const simplex = (s, t) =>
choose (s + t - 1, t)
console.log ('simplex (3, 3): ', simplex (3, 3))
.as-console-wrapper {max-height: 100% !important; top: 0}