Markus
10/6/2004 11:15:00 PM
There were about five minor problems (three missing to_s's, a
scoping issue with LotteryDraw's play & @@tickets, and a redo that
should have been a recursive call.
I tried to change the structure as little as possible, so that you
can see what I did.
-- Markus
class LotteryTicket
NUMERIC_RANGE = 1..25
attr_reader :picks, :purchased
def initialize( *picks )
if picks.length != 3
raise ArgumentError, "three numbers must be picked"
elsif picks.uniq.length != 3
raise ArgumentError, "the three picks must be different
numbers"
elsif picks.detect { |p| not NUMERIC_RANGE === p }
raise ArgumentError, "the three picks must be numbers
between 1 and 25."
end
@picks = picks
@purchased = Time.now
end
end
class LotteryTicket
def self.new_random
new( rand( 25 ) + 1, rand( 25 ) + 1, rand( 25 ) + 1 )
rescue ArgumentError
new_random
end
end
class LotteryDraw
@@tickets = {}
def LotteryDraw.buy( customer, *tickets )
unless @@tickets.has_key?( customer )
@@tickets[customer] = []
end
@@tickets[customer] += tickets
end
end
LotteryDraw.buy 'Yal-dal-rip-sip',
LotteryTicket.new( 12, 6, 19 ),
LotteryTicket.new( 5, 1, 3 ),
LotteryTicket.new( 24, 6, 8 )
class LotteryTicket
def score( final )
count = 0
final.picks.each do |note|
count +=1 if picks.include? note
end
count
end
end
class LotteryDraw
def self.play
final = LotteryTicket.new_random
winners = {}
@@tickets.each do |buyer, ticket_list|
ticket_list.each do |ticket|
score = ticket.score( final )
next if score.zero?
winners[buyer] ||= []
winners[buyer] << [ ticket, score ]
end
end
@@tickets.clear
winners
end
end
LotteryDraw.play.each do |winner, tickets|
puts winner + "won on " + tickets.length.to_s + " ticket(s)!"
tickets.each do |ticket, score|
puts "\t" + ticket.picks.join( ', ' ) + ": " + score.to_s
end
end
On Wed, 2004-10-06 at 15:43, mailinglist_abe@yahoo.com wrote:
> Hey, I've been an avid reader of the Why's Poignant Guide to Ruby ever since
> I discovered it (poignantguide.net), but while the material is excellent, it
> is reduced in effectiveness because I'm reasonably certain that the writer
> doesn't run (verbatim anyway) the code that he puts in some of the
> tutorials. Namely, I'm having trouble getting a "lottery" tutorial to work,
> and I'm too much of a Newb to see easily what the problem is. When I run the
> code I get an error like so: "warning: class variable access from toplevel
> singleton method"
>
>
>
> My code is below, would anyone mind please skimming it and letting me know
> what the errant code is? I appreciate it!
>
>
>
> Regards, Abe
>
>
>
> p.s. the code below is verbatim from the guide itself - I thought that
> perhaps I'd mistyped something and so I copied and pasted the code into
> Mondrian (the IDE I'm using)
>
>
>
> class LotteryTicket
>
>
>
> NUMERIC_RANGE = 1..25
>
>
>
> attr_reader :picks, :purchased
>
>
>
> def initialize( *picks )
>
> if picks.length != 3
>
> raise ArgumentError, "three numbers must be picked"
>
> elsif picks.uniq.length != 3
>
> raise ArgumentError, "the three picks must be different numbers"
>
> elsif picks.detect { |p| not NUMERIC_RANGE === p }
>
> raise ArgumentError, "the three picks must be numbers between 1 and
> 25."
>
> end
>
> @picks = picks
>
> @purchased = Time.now
>
> end
>
>
>
> end
>
>
>
> class LotteryTicket
>
> def self.new_random
>
> new( rand( 25 ) + 1, rand( 25 ) + 1, rand( 25 ) + 1 )
>
> rescue ArgumentError
>
> redo
>
> end
>
> end
>
>
>
> class LotteryDraw
>
> @@tickets = {}
>
> def LotteryDraw.buy( customer, *tickets )
>
> unless @@tickets.has_key?( customer )
>
> @@tickets[customer] = []
>
> end
>
> @@tickets[customer] += tickets
>
> end
>
> end
>
>
>
> LotteryDraw.buy 'Yal-dal-rip-sip',
>
> LotteryTicket.new( 12, 6, 19 ),
>
> LotteryTicket.new( 5, 1, 3 ),
>
> LotteryTicket.new( 24, 6, 8 )
>
>
>
> class LotteryTicket
>
> def score( final )
>
> count = 0
>
> final.picks.each do |note|
>
> count +=1 if picks.include? note
>
> end
>
> count
>
> end
>
> end
>
>
>
> class << LotteryDraw
>
> def play
>
> final = LotteryTicket.new_random
>
> winners = {}
>
> @@tickets.each do |buyer, ticket_list|
>
> ticket_list.each do |ticket|
>
> score = ticket.score( final )
>
> next if score.zero?
>
> winners[buyer] ||= []
>
> winners[buyer] << [ ticket, score ]
>
> end
>
> end
>
> @@tickets.clear
>
> winners
>
> end
>
> end
>
>
>
> LotteryDraw.play.each do |winner, tickets|
>
> puts winner + "won on " + tickets.length + " ticket(s)!"
>
> tickets.each do |ticket, score|
>
> puts "\t" + ticket.picks.join( ', ' ) + ": " + score
>
> end
>
> end
>