双重可乐挑战,JavaScript代码错误?
五个朋友在排队喝魔可乐。当第一个朋友喝可乐时,他消失了,并复制成两份!在那之后,这些新的拷贝到了队列的末尾,下一个朋友喝了魔可乐,重复这个过程 例如,假设我们有以下朋友:双重可乐挑战,JavaScript代码错误?,javascript,challenge-response,Javascript,Challenge Response,五个朋友在排队喝魔可乐。当第一个朋友喝可乐时,他消失了,并复制成两份!在那之后,这些新的拷贝到了队列的末尾,下一个朋友喝了魔可乐,重复这个过程 例如,假设我们有以下朋友: [Sheldon, Leonard, Penny, Rajesh, Howard] 谢尔顿喝下第一杯可乐后,队伍将如下所示: [Leonard, Penny, Rajesh, Howard, Sheldon, Sheldon] [Penny, Rajesh, Howard, Sheldon, Sheldon, Leonar
[Sheldon, Leonard, Penny, Rajesh, Howard]
谢尔顿喝下第一杯可乐后,队伍将如下所示:
[Leonard, Penny, Rajesh, Howard, Sheldon, Sheldon]
[Penny, Rajesh, Howard, Sheldon, Sheldon, Leonard, Leonard]
莱纳德喝了可乐后,台词是这样的:
[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, 52), "Penny");
如果我尝试使用一个非常大的数字,比如:
names = ["Sheldon", "Leonard", "Penny", "Rajesh", "Howard"];
Test.assertEquals(whoIsNext(names, 7230702951), "Leonard");
它甚至不会停止运行(需要永远)
所以很明显,我的解决方案不仅不正确,而且似乎也不完善。如何修复它?一个基于零的递归建议,返回数组的索引,这里的长度
base=5
当它变为可见时,模式以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;
函数getIndex(n,i){
i=i | |基;
if(n”);//“谢尔顿”
写(friends[getIndex(52-1)]+“
”);//“便士”
写(friends[getIndex(7230702951-1)]+“
”;//“伦纳德”
对于(i=0;i<200;i++){
index=getIndex(i);
写(i+':'+索引+''+朋友[索引]+'
);
}
好了,我们开始吧,这是一个非常简单的方法,我会想出一个更好的方法(我已经想了一半,我只需要把它组合起来)
函数whoIsNext(名称、索引、乘数)
{
var count=names.length;
var=0;
风险价值指数=0;
while(货币指数)
{
返回名称[i];
}
}
fullLoops++;
}
}
这个想法是,每次人们做一个完整的循环时,同一个人来的数量会翻倍(countPerson=Math.pow(2,countFullLoops)
)。如果你在设定的索引之前累积人数,直到你达到索引,你就会找到合适的人(我觉得我只是解释了一件非常简单的事情,非常困难)
此外,您还可以根据需要替换任何输入(更改开始时的人数,更改乘法因子(有人说四倍可乐吗?)。为什么要推两次?@epascarello,因为这不是一个简单的队列-从前面移除时,条目会在最后重复。这就是为什么它是一个更难的谜题。我错过了…咖啡还没有开始。为什么不采取数学方法呢?毕竟,每次通过每个人时,你总是附加两倍数量的名字。。。应该有一个清晰的模式可以识别,这可能是通过得到比你的支票号码低2倍的最高组合来计算的。从这里开始计算,直到得到一个介于0和4之间的数字,然后得到索引。应该不需要一直计算。目前在工作中,我将在大约。。。2小时或更长的时间,你的函数会考虑到一个事实,即名字是重复的,而其他名字不是重复的?此外,数组不会每轮大小增加一倍。我不明白它是怎么做到的。它只是上升了1个值。仔细想想,从队列中删除一个值,然后添加2个值。总偏移量为+1。其余的保持不变。因此,如果数组有5个名称,在第一次运行后,它将有6个,而不是10个@菲尼克斯,你在哪里看到10?啊,明白了!就是这样!
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++;
}
}