From: Markus Date: 2004-10-07T08:14:44+09:00 Subject: Re: Help! Newb having trouble getting a WHY'S example to work... 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 >