双重可乐挑战,JavaScript代码错误



五个朋友正在排队喝魔性可乐。当第一个朋友喝下可乐时,他消失了,并复制成两份!在那之后,这些新的副本进入行的末尾,下一个朋友喝下神奇的可乐,重复这个过程。

例如,假设我们有以下朋友:

[Sheldon, Leonard, Penny, Rajesh, Howard]

Sheldon喝了第一杯可乐后,队伍会是这样的:

[Leonard, Penny, Rajesh, Howard, Sheldon, Sheldon]

伦纳德喝了可乐后,队伍变成这样:

[Penny, Rajesh, Howard, Sheldon, Sheldon, Leonard, Leonard]

等等…

我的目标是用JavaScript编写一个函数,给定一个数组,其中包含行中的人名和数字N,它将返回喝神奇可乐的第N个人的名字。

因此,例如,执行console.log(whoIsNext([Sheldon, Leonard, Penny, Rajesh, Howard], 1))应该返回Sheldon

为了实现这一点,我制作了以下代码:

function whoIsNext(names, r){
  var fistInLine;
  if(r <= names.length){
    return names[r-1];
  }else{
    while(r > names.length){
      fistInLine = names.shift();
      names.push(fistInLine, fistInLine);
    }
    return names[r-1];
  }
}

此功能适用于以下情况:

names = ["Sheldon", "Leonard", "Penny", "Rajesh", "Howard"];
Test.assertEquals(whoIsNext(names, 1), "Sheldon");

但测试失败:

names = ["Sheldon", "Leonard", "Penny", "Rajesh", "Howard"];
Test.assertEquals(whoIsNext(names, 52), "Penny");

如果我尝试使用一个非常大的数字,比如:

names = ["Sheldon", "Leonard", "Penny", "Rajesh", "Howard"];
Test.assertEquals(whoIsNext(names, 7230702951), "Leonard");

它甚至不会停止运行(需要很长时间)。

很明显,我的解决方案不仅不正确,而且似乎也不够有效。我该怎么修?

一个基于零的递归建议,它返回数组的索引,这里的长度为base = 5

                           1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3
number 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
index  0 1 2 3 4 0 0 1 1 2 2 3 3 4 4 0 0 0 0 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 0 0 0 0 0

它变得可见,图案以5为基础,每一轮都会增加因子2。

5 -> 10- > 20 -> 40

计算示例

                Array after step
                0 1 2 3 4 5 6 7 8 9 
  0: 0 Sheldon  | 
  1: 1 Leonard  | |
  2: 2 Penny    | | |
  3: 3 Rajesh   | | | |
  4: 4 Howard   | | | | |
  5: 0 Sheldon    | | | | |
  6: 0 Sheldon    | | | | | |
  7: 1 Leonard      | | | | | |
  8: 1 Leonard      | | | | | | |
  9: 2 Penny          | | | | | |
 10: 2 Penny          | | | | | |
 11: 3 Rajesh           | | | | |
 12: 3 Rajesh           | | | | |
 13: 4 Howard             | | | |
 14: 4 Howard             | | | |
 15: 0 Sheldon              | | |
 16: 0 Sheldon              | | |
 17: 0 Sheldon                | |
 18: 0 Sheldon                | |
 19: 1 Leonard                  |
 20: 1 Leonard                  |
 21: 1 Leonard
 22: 1 Leonard

var friends = ['Sheldon', 'Leonard', 'Penny', 'Rajesh', 'Howard'],
    base = friends.length;
function getIndex(n, i) {
    i = i || base;
    if (n < i) {
        return Math.floor(n * base / i);
    }
    return getIndex(n - i, 2 * i);
}
var i = 0, index;
document.write(friends[getIndex(1 - 1)] + '<br>');          // "Sheldon"
document.write(friends[getIndex(52 - 1)] + '<br>');         // "Penny"
document.write(friends[getIndex(7230702951 - 1)] + '<hr>'); // "Leonard"
for (i = 0; i < 200; i++) {
    index = getIndex(i);
    document.write(i + ': ' + index + ' ' + friends[index] + '<br>');
}

好吧,开始吧,这是一个非常简单的方法,我会想出一个更好的方法(我已经想了一半,我只需要把它组合在一起)

function whoIsNext(names, index, multiplyFactor)
{
    var count = names.length;
    var fullLoops = 0;
    var currIndex = 0;
    while(currIndex <= index)
    {
        for(var i = 0; i < count; i++)
    {
            currIndex += Math.pow(multiplyFactor, fullLoops);
            if(currIndex > index)
            {
            return names[i];
            }
        }
        fullLoops++;
    }
}

这个想法是,每次人们做一个完整的循环(countPerson = Math.pow(2, countFullLoops)),同一个人来的数量就会翻倍。如果你在设定指数之前积累人数,直到达到指数,你就会找到合适的人(我觉得我只是解释了一件非常简单的事情,非常困难)。

此外,你可以根据自己的意愿替换任何输入(改变开始时的人数,改变乘法系数(有人说是四倍可乐吗?))。

相关内容

  • 没有找到相关文章

最新更新