问题描述
|
我编写了一个Secret Santa程序(ala Ruby Quiz ... ish),但偶尔在该程序运行时出现错误。
统计:如果底池中有10个名字,则错误出现的时间约为5%。如果底池中有100个名字,则少于1%。这是对bash的1000次试用。我确定礼物阵列在某个时候几乎为零,但是我不确定为什么或如何避免这种情况。
提供代码...
0.upto($lname.length-1).each do |i|
j = rand($giftlname.length) # should be less each time.
while $giftlname[j] == $lname[i] # redo random if it picks same person
if $lname[i] == $lname.last # if random gives same output again,means person is left with himself; needs to switch with someone
$giftfname[j],$fname[i] = $giftfname[i],$fname[j]
$giftlname[j],$lname[i] = $giftlname[i],$lname[j]
$giftemail[j],$email[i] = $giftemail[i],$email[j]
else
j = rand($giftlname.length)
end
end
$santas.push(\'Santa \' + $fname[i] + \' \' + $lname[i] + \' sends gift to \' + $giftfname[j] + \' \' + $giftlname[j] + \' at \' + \'<\' + $giftemail[j] + \'>.\') #Error here,something is sometimes nil
$giftfname.delete_at(j)
$giftlname.delete_at(j)
$giftemail.delete_at(j)
end
非常感谢!
解决方法
我认为您的问题就在这里:
$giftfname[j],$fname[i] = $giftfname[i],$fname[j]
您的i
值的范围在零到$fname
(包括端值)中的最后一个索引之间,并且大概您的$giftfname
作为$fname
的克隆(或至少另一个相同长度的数组)开始。但是,当您旋转each
时,您正在缩小$giftfname
,因此$giftfname[i]
将成为nil
,并且上面的swap操作会将nil
放入$giftfname[j]
(这应该是$giftfname
的有用项)。类似的问题适用于$giftlname
和$giftemail
。
我建议将一个数组与三个元素对象(名字,姓氏,电子邮件)一起使用,而不要使用三个并行数组。 Array上还有一个a15ѭ方法可能对您有用:
从众多的人开始。
复制该数组。
将副本随机播放,直到每个索引与原始数组都不同为止。
然后将zip
在一起,以获得最终的送受者对列表。
, 弄清楚了,并使用了retry语句。现在,if语句如下所示(所有其他变量也已被编辑为非全局变量)
if lname[i] == lname.last
santas = Array.new
giftfname = fname.clone
giftlname = lname.clone
giftemail = email.clone
retry
除了进行其他一些编辑外,该方法还创建了我需要的解决方案,而又不会再次拆分太多代码。当然也可以尝试mu的解决方案,但是很高兴我现在可以无错运行了。