开发者

Can't convert nil into string--Ruby Secret Santa

I wrote a Secret Santa program (ala Ruby Quiz...ish), but occasionally when the program runs, I get an error. Stats: If there's 10 names in the pot, the error comes up about 5% of the time. If there's 100 names in the pot, it's less than 1%. This is on a trial of 1000 times in bash. I've determined that the gift arrays are coming up nil at some point, but I'm not sure why or how to avoid it. Providing code...

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]
      $gi开发者_如何转开发ftlname[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

Thanks SO!


I think your problem is right here:

$giftfname[j], $fname[i] = $giftfname[i], $fname[j]

Your i values range between zero to the last index in $fname (inclusive) and, presumably, your $giftfname starts off as a clone of $fname (or at least another array with the same length). But, as you spin through the each, you're shrinking $giftfname so $giftfname[i] will be nil and the swap operation above will put nil into $giftfname[j] (which is supposed to be a useful entry of $giftfname). Similar issues apply to $giftlname and $giftemail.

I'd recommend using one array with three element objects (first name, last name, email) instead of your three parallel arrays. There's also a shuffle method on Array that might be of use to you:

  • Start with an array of people.
  • Make copy of that array.
  • Shuffle the copy until it is different at every index from that original array.
  • Then zip the together to get your final list of giver/receiver pairs.


Figured it out and used the retry statement. the if statement now looks like this (all other variables have been edited to be non-global as well)

if lname[i] == lname.last 
  santas = Array.new
  giftfname = fname.clone
  giftlname = lname.clone
  giftemail = email.clone
  retry  

That, aside from a few other edits, created the solution I needed without breaking apart the code too much again. Will definitely try out mu's solution as well, but I'm just glad I have this running error-free for now.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜