Hello!

I realised that my implementation is rather flawed, and rather late, so 
decided to not bother with the less exciting SMTP bit. Also, while 
testing (which failed :) I was using DATA instead of STDIN. I just left 
it like this; I find very useful, and am keen to spread the love. (This 
means that the end of the file is under the "Lindsey Brigman" line, not 
where it says __END__)

Occasionally it freaks out and is unable to assign valid santas to 
either the last or second-last persons, as they've already been 
assigned elsewhere. A cleverer friend helpfully suggested "looks like 
you need some cleverer algorithm"...

I think that if implementing this again I'd just build two identical 
lists of people, and keep swapping them around randomly until it was 
all good. Less efficient, but more likely to eventually come up with 
the goods reliably.

Had lots of fun doing this!

  - Peter

#!/usr/bin/env ruby

class Person
   attr_reader :sname, :email
   attr_accessor :santa
   def initialize(details)
     @fname, @sname, @email = details.scan(/(\w+)\s+(\w+)\s+<(.*)>/)[0]
   end
   def to_s() @fname + " " + @sname end
   def status()
     if @santa then self.to_s + " is santa'd to " + @santa.to_s
     else self.to_s + " is santa-less!\a" end # Ooh... beeps.
   end
end

families = Hash.new {[]}
unchosen = []

DATA.each do |l|
   someone = Person.new(l)
   families[someone.sname] <<= someone
   unchosen << someone
end

families.keys.each do |sname|
   choices = unchosen.dup.delete_if { |someone| someone.sname == sname }
   families[sname].each do |person|
     person.santa = 
unchosen.delete(choices.delete_at(rand(choices.length)))
     puts person.status
   end
end

__END__
Luke Skywalker <luke / theforce.net>
Leia Skywalker <leia / therebellion.org>
Toula Portokalos <toula / manhunter.org>
Gus Portokalos <gus / weareallfruit.net>
Bruce Wayne <bruce / imbatman.com>
Virgil Brigman <virgil / rigworkersunion.org>
Lindsey Brigman <lindsey / iseealiens.net>