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