如何让数字在 JavaScript 中的特定范围内循环?

How to get numbers to cycle around specific range in JavaScript?

我有这个不工作,像 1 2 3 4 5 6 7 8 9 1 2 3 4 ... 这样的循环,在 1 和 9 之间循环。

const cycle = integers => {
  let i = 0
  let x = integers[i++]
  while (i < integers.length) {
    let y = integers[i++]
    const s = x + y
    const remainder = (s % 9) + 1
    x = remainder
  }
  return (x - 1) % 9
}

logCycle([ 9, 6 ])
logCycle([ 9, 9 ])
logCycle([ 9, 9, 9, 9, 9 ])
logCycle([ 9, 129, 993, 91, 9 ])
logCycle([ 9, 10 ])

function logCycle(i) {
  log('cycle', i, cycle(i))
}

function log(t, i, o) {
  console.log(`${t}(${JSON.stringify(i)}) => ${o}`)
}

注意在 cycle([9, 9]) 它是如何返回 0 的,在其他地方它也发生了故障。 cycle 函数采用任意长度的整数数组。所以数组可能有 1000000 个项目,或者只有 2 个。

我预计:

如何让它正常工作?我如何让它适用于任何一对 min/max 数字,比如如果我想在(包括)5 和 13,或 79 和 5337 之间循环,我如何让它像那样通用?

cycle 函数对结果进行求和和取模,使其理想地在该范围内“循环”。它不是循环迭代,而是“循环求和”,就像一个时钟。

还希望保持解决方案的非递归性,因为 array 中的元素数量可能很大。

显然我一开始误解了问题的某些部分。在阅读了更多评论后,我觉得

  • 要遍历的数字可以是任何先前定义的序列,例如从 1 到 9、从 5 到 13 或从 79 到 5337
  • (重复)上述序列的总步数由 循环函数所有参数的总和给出。

对于这些要求,以下应该有效:

function defCycle(m,n){
    const base=n-m+1,off=m-1;  // base: sequence-length,  off: offset of sequence
    return arr=>(arr.reduce((a,c)=>a+c)%base||base)+off;
};

// run the function on a collection of test data:
const ntest=1000000;
[[1,9],[5,13],[79,5337]]
.forEach(([m,n],cycle)=>{
  console.log(`Sequence from ${m} to ${n}:`);
  cycle=defCycle(m,n);
  [[ 9, 6 ],[ 9, 9 ],[ 9, 9, 9, 9, 9 ],[ 9, 129, 993, 91, 9 ],[ 9, 10 ],[1, 811, 29317, 391, 21],[ntest*(ntest+1)/2]]
  .forEach(arr=>console.log(`cycle(${JSON.stringify(arr)}) => ${cycle(arr)}`));
  console.log(`cycle([1,2,3,...,${ntest}]) => ${cycle([...Array(ntest)].map((_,i)=>i+1))}`);
});

最后两个测试用例应该产生完全相同的结果:遍历从 1 到 1000000 的序列数组的总和 ( = (1000000*1000001)/2) 应该导致 1 (对于序列:“1...9”)。

defCycle() 函数中的操作发生在这两行中:

  1. base=n-m+1,off=m-1;
    base: 序列元素
    off: 序列
    偏移量 示例(从 5 到 11 的序列):m=5,n=11 => base=7,off=4
  2. return arr=>(arr.reduce((a,c)=>a+c)%base||base)+off;
    这个returns一个singe-argument-function基于之前计算的baseoff。计算由两个表达式组成:
    • [shift] = (arr.reduce((a,c)=>a+c) 总结了作为参数传递的 arr 的所有元素 - 和
    • [shift]%base||base 计算实际结果:总数 [shift] 的模数(基数)。每当结果 ==0 它被替换为 base 值。

如果你只需要结果(循环时不需要执行其他操作),那么你可以很容易地使用基础转换来计算它。

function getResult(base, num) {
  const str = (parseInt((num-1).toString(base)) + 1).toString()
  return str.charAt(str.length - 1)
}

console.log( getResult(9, 6) ) // 6

console.log( getResult(9, 9) ) // 9

console.log( getResult(9, 10) ) // 1