# \[QUIZ\] Checking Credit Cards (#122)

**URL:** <https://www.ruby-forum.com/t/quiz-checking-credit-cards-122/103116>\
**Category:** Ruby\
**Created:** [May 2, 2007, 12:21am UTC](https://www.ruby-forum.com/t/quiz-checking-credit-cards-122/103116 "2007-05-02T00:21:11Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Brian\_Krahmer](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/8dc957/32.png) [@Brian\_Krahmer](https://www.ruby-forum.com/u/Brian_Krahmer)\
**Post date:** [May 2, 2007, 12:21am UTC](https://www.ruby-forum.com/t/quiz-checking-credit-cards-122/103116/1 "2007-05-02T00:21:11Z")

</div>

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
