And here is my version of the second quiz. It does not use 'net/smtp' but shows the chosen santas on the console.
Thomas
-----------------------------------------------
#!/usr/bin/env ruby
Person = Struct.new( :first, :last, :email )
# Parses one line and extract the data items
def parse_name( name )
person = Person.new( *name.split[0..2] )
if person.first.nil? || person.last.nil? || person.email.nil?
puts "Invalid input: #{name.inspect}"
exit
end
return person
end
# Reads lines from the given IO object and returns a Hash with all persons as keys
def parse_names( io )
list = {}
list[parse_name( STDIN.readline )] = nil until io.eof
return list
end
# Associates each person with a list of possibile Santas
def build_santa_lists( list )
list.each_key do |person|
possible_santas = list.keys
possible_santas.reject! { |other_person| other_person.last == person.last }
list[person] = possible_santas
end
end
# A Santa is correct if there is no other person for whom only the selected Santa is left
def verify_santa( list, person, santa )
list.each do |key, value|
return false if key != person && value == [santa]
end
return true
end
# Choose a Santa for each person
def choose_santas( list )
list.each do |person, possible_santas|
begin santa = possible_santas[rand( possible_santas.length )] end until verify_santa( list, person, santa )
list.each_value { |value| value.delete( santa ) if Array === value }
list[person] = santa
end
end
# Mail the Santas which person they have got
def mail_santas( list )
list.each do |person, santa|
santa = Person.new('<no valid santa found>', '', '') if santa.nil?
puts "Santa #{santa.first} #{santa.last} #{santa.email} for #{person.first} #{person.last} #{person.email}"
end
end
list = parse_names( STDIN )
build_santa_lists list
choose_santas list
mail_santas list