From: James Edward Gray II on 2 May 2007 09:57 On Apr 29, 2007, at 1:17 PM, Brad Ediger wrote: > # Maps n-at-a-time (n = arity of given block) and collects the > results > def mapn(&b) > r = [] > each_slice(b.arity) {|*args| r << b.call(*args) } > r > end That's pretty darn clever. You can collapse it to one line with inject() of course: def mapn(&b) enum_slice(b.arity).inject([]) {|r, args| r << b.call(*args) } end James Edward Gray II From: Christian Neukirchen on 2 May 2007 11:13 Ruby Quiz writes: > This week's Ruby Quiz is to write a program that accepts a credit card number as > a command-line argument. The program should print the card's type (or Unknown) > as well a Valid/Invalid indication of whether or not the card passes the Luhn > algorithm. #!ruby def cardtype(n) case n.delete("^0-9") when /\A3[37]\d{13}\z/: "AMEX" when /\A6011\d{12}\z/: "Discover" when /\A5[1-4]\d{14}\z/: "Master Card" when /\A4\d{12}\d{3}?\z/: "Visa" else "Unknown" end end def luhn?(n) f = 2 (n.delete("^0-9").reverse.split(//).map{|d|d.to_i}. inject(0) { |a,e| f=3-f; a + (e*f > 9 ? e*f-9 : e*f) } % 10).zero? end puts cardtype(ARGV.join) puts luhn?(ARGV.join) ? "valid" : "invalid" __END__ -- Christian Neukirchen http://chneukirchen.org From: Brad Ediger on 2 May 2007 12:44 On May 2, 2007, at 8:57 AM, James Edward Gray II wrote: > On Apr 29, 2007, at 1:17 PM, Brad Ediger wrote: > >> # Maps n-at-a-time (n = arity of given block) and collects the >> results >> def mapn(&b) >> r = [] >> each_slice(b.arity) {|*args| r << b.call(*args) } >> r >> end > > That's pretty darn clever. You can collapse it to one line with > inject() of course: > > def mapn(&b) > enum_slice(b.arity).inject([]) {|r, args| r << b.call(*args) } > end Didn't even think about inject here. Awesome. I'm sure that I'm going to be using mapn more, as it's cool. I can't take credit for the mapn concept though: eachn is a Facets function I stumbled across. --be From: Dennis Frommknecht on 2 May 2007 13:14 Am 02.05.2007 um 17:13 schrieb Christian Neukirchen: > Ruby Quiz writes: > >> This week's Ruby Quiz is to write a program that accepts a credit >> card number as >> a command-line argument. The program should print the card's type >> (or Unknown) >> as well a Valid/Invalid indication of whether or not the card >> passes the Luhn >> algorithm. > > #!ruby > > def cardtype(n) > case n.delete("^0-9") > when /\A3[37]\d{13}\z/: "AMEX" > when /\A6011\d{12}\z/: "Discover" > when /\A5[1-4]\d{14}\z/: "Master Card" > when /\A4\d{12}\d{3}?\z/: "Visa" > else "Unknown" > end > end > > def luhn?(n) > f = 2 > (n.delete("^0-9").reverse.split(//).map{|d|d.to_i}. > inject(0) { |a,e| f=3-f; a + (e*f > 9 ? e*f-9 : e*f) } % > 10).zero? > end > > puts cardtype(ARGV.join) > puts luhn?(ARGV.join) ? "valid" : "invalid" > > __END__ > > -- > Christian Neukirchen http:// > chneukirchen.org > > Wow, very nice solution! Impressive how short it is... Here is my solution: #!/usr/bin/env ruby -W # Assign a regular expression that checks first characters and length PROVIDERINFO = { "AMEX" => /^(34|37)\d{13}\$/, "Discover" => /^6011\d{12}\$/, "MasterCard" => /^5[1-5]\d{14}\$/, "Visa" => /^4(\d{12}|\d{15})\$/, } class CreditCard attr_reader :provider, :number def initialize(number) @number = [] # split credit card number and store in array number.scan(/\d/){|c| @number.push c.to_i} # Check Provider Infos @provider = "Unknown" PROVIDERINFO.each_pair {|k, v| @provider = k if @number.join.match(v) } end def luhn_passed? sum = 0 @number.reverse.each_with_index do |num, i| # double the nummer if necessary and subtract 9 if the result # consists of 2 numbers (here same as summing up both numbers) num = num * 2 - ((num > 4) ? 9 : 0) if i % 2 == 1 sum += num end sum % 10 == 0 end def to_s "Creditcard number #{@number}\n" + " Provider: #{self.provider}\n" + " Luhn Algorithm #{'not ' unless self.luhn_passed?}passed" end end puts CreditCard.new(ARGV.join) Regards, Dennis Frommknecht From: Pit Capitain on 2 May 2007 13:26 James Edward Gray II schrieb:> That's pretty darn clever. You can collapse it to one line with > inject() of course: > > def mapn(&b) > enum_slice(b.arity).inject([]) {|r, args| r << b.call(*args) } > end Simpler: def mapn(&b) to_enum(:each_slice, b.arity).map(&b) end Regards, Pit First  |  Prev  |  Next  |  Last