From: Philip Gatt Date: 2007-04-30T02:40:11+09:00 Subject: Re: [QUIZ][SOLUTION] Checking Credit Cards (#122) This is my first rubyquiz. Here is my solution. class CreditCard class CardType < Struct.new(:name, :regex, :accepted_lengths) def valid_length?(length) if accepted_lengths.is_a?(Array) return accepted_lengths.include?(length) else return accepted_lengths == length end end end CARD_TYPES = [CardType.new('AMEX', /^3[47]/, 15), CardType.new('Discover', /^6011/, 16), CardType.new('MasterCard', /^5[1-5]/, 16), CardType.new('Visa', /^4/, [13, 16]), CardType.new('Unknown', /.*/, 0)] def initialize(number) @number = number @card_type = CARD_TYPES.find {|t| @number =~ t.regex } end def card_type @card_type.name end def valid? return false unless @card_type.valid_length?(@number.length) numbers = @number.split(//).collect {|x| x.to_i} i = numbers.length - 2 while i >= 0 numbers[i] *= 2 i -= 2 end numbers = numbers.to_s.split(//) sum = 0; numbers.each {|x| sum += x.to_i} sum % 10 == 0 end end abort "Usage: #{$0} card_number [...]" if ARGV.empty? ARGV.each do |card_number| c = CreditCard.new(card_number) out = "#{card_number}: " out += (c.valid? ? "Valid " : "Invalid ") out += "#{c.card_type}" puts out end