Am 02.05.2007 um 17:13 schrieb Christian Neukirchen: > Ruby Quiz <james / grayproductions.net> 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 <chneukirchen / gmail.com> 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