双倍可乐挑战,JavaScript密码错误?

Double Cola Challenge, JavaScript code wrong?

五个朋友在排队喝魔法可乐。当第一个朋友喝了可乐,他就消失了,并且繁殖成两份!在那之后,那些新的副本到行尾,下一个朋友喝魔法可乐,重复这个过程。

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

[Sheldon, Leonard, Penny, Rajesh, Howard]

Sheldon 喝完第一口可乐后,该行将如下所示:

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

伦纳德喝完可乐后,台词变成了这样:

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

等等...

我的objective是在JavaScript中写了一个函数,给定一个数组,其中包含行中的人的名字,以及一个数字N,它将return第N个喝魔法可乐的人的名字。

所以,例如,做 console.log(whoIsNext([Sheldon, Leonard, Penny, Rajesh, Howard], 1)) 应该 return 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");

它甚至不会停止 运行(永远)。

很明显,我的解决方案不仅不正确,而且似乎也很低效。我该如何解决?

一个基于零的递归提议,其中 returns 数组的索引,这里的长度为 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

It become visible, the pattern is based on 5 and goes up for every round by factor 2.

5 -> 10- > 20 -> 40

Example of calculation

                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))。如果再累积到设定指标之前的人数,直到达到指标,就找到合适的人了(我感觉我只是解释了一个很简单的事情真的很难)。

您也可以根据需要替换任何输入(更改开始时的人数,更改乘数(有人说四重可乐吗?))。