B
Brian Krahmer
Here is my submission. My first version was a bit shorter and more
concise, where I had embedded the allowed lengths into the regex. I
already had it written before the topic of 12 digits starting with 4
came up. So, upon James' first decision to call that an invalid Visa, I
refactored and left it that way.
cheers,
brian
if ARGV.size == 0
puts "You must supply a credit card number to be checked."
abort
end
input = ARGV.join
class CardCompany
class << self
def is_issuer_of?(data)
data =~ self::ValidRegex
end
def valid_card?(data)
return false if invalid_length?(data)
reversed = data.reverse
sum = 0
1.step(reversed.length - 1, 2) do |i|
digit = reversed[i..i].to_i
if digit < 5
sum += digit * 2
else
sum += ((digit * 2) % 10) + 1
end
end
0.step(reversed.length - 1, 2) do |i|
sum += reversed[i..i].to_i
end
sum % 10 == 0
end
def invalid_length?(data)
return false if self::ValidLengths.empty?
for length in self::ValidLengths
return false if data.size == length
end
true
end
end
end
class AmexCardCo < CardCompany
ValidRegex = /^3[47]\d+$/
ValidLengths = [15]
Name = 'AMEX'
end
class DiscoCardCo < CardCompany
ValidRegex = /^6011\d+$/
ValidLengths = [16]
Name = 'Discover'
end
class MasterCardCo < CardCompany
ValidRegex = /^5[1-5]\d+$/
ValidLengths = [16]
Name = 'MasterCard'
end
class VisaCardCo < CardCompany
ValidRegex = /^4\d+$/
ValidLengths = [13, 16]
Name = 'Visa'
end
class UnknownCardCo < CardCompany
ValidRegex = /^\d+$/
ValidLengths = []
Name = 'Unknown'
end
SYSTEMS = [ AmexCardCo, DiscoCardCo, MasterCardCo, VisaCardCo,
UnknownCardCo ]
for system in SYSTEMS
if system.is_issuer_of?(input)
found = true
valid = system.valid_card?(input)
puts "#{system::Name} #{valid ? 'Valid' : 'Invalid'}"
break
end
end
puts "Invalid input" if !found
concise, where I had embedded the allowed lengths into the regex. I
already had it written before the topic of 12 digits starting with 4
came up. So, upon James' first decision to call that an invalid Visa, I
refactored and left it that way.
cheers,
brian
if ARGV.size == 0
puts "You must supply a credit card number to be checked."
abort
end
input = ARGV.join
class CardCompany
class << self
def is_issuer_of?(data)
data =~ self::ValidRegex
end
def valid_card?(data)
return false if invalid_length?(data)
reversed = data.reverse
sum = 0
1.step(reversed.length - 1, 2) do |i|
digit = reversed[i..i].to_i
if digit < 5
sum += digit * 2
else
sum += ((digit * 2) % 10) + 1
end
end
0.step(reversed.length - 1, 2) do |i|
sum += reversed[i..i].to_i
end
sum % 10 == 0
end
def invalid_length?(data)
return false if self::ValidLengths.empty?
for length in self::ValidLengths
return false if data.size == length
end
true
end
end
end
class AmexCardCo < CardCompany
ValidRegex = /^3[47]\d+$/
ValidLengths = [15]
Name = 'AMEX'
end
class DiscoCardCo < CardCompany
ValidRegex = /^6011\d+$/
ValidLengths = [16]
Name = 'Discover'
end
class MasterCardCo < CardCompany
ValidRegex = /^5[1-5]\d+$/
ValidLengths = [16]
Name = 'MasterCard'
end
class VisaCardCo < CardCompany
ValidRegex = /^4\d+$/
ValidLengths = [13, 16]
Name = 'Visa'
end
class UnknownCardCo < CardCompany
ValidRegex = /^\d+$/
ValidLengths = []
Name = 'Unknown'
end
SYSTEMS = [ AmexCardCo, DiscoCardCo, MasterCardCo, VisaCardCo,
UnknownCardCo ]
for system in SYSTEMS
if system.is_issuer_of?(input)
found = true
valid = system.valid_card?(input)
puts "#{system::Name} #{valid ? 'Valid' : 'Invalid'}"
break
end
end
puts "Invalid input" if !found