On Apr 27, 6:59 pm, Ruby Quiz <j... / grayproductions.net> wrote:
> The three rules of Ruby Quiz:
>
> 1.  Please do not post any solutions or spoiler discussion for this quiz until
> 48 hours have passed from the time on this message.
>
> 2.  Support Ruby Quiz by submitting ideas as often as you can:
>
> http://www.rubyquiz.com/
>
> 3.  Enjoy!
>
> Suggestion:  A [QUIZ] in the subject of emails about the problem helps everyone
> on Ruby Talk follow the discussion.  Please reply to the original quiz message,
> if you can.
>
>
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
=-=-=-=-=
>
> Before a credit card is submitted to a financial institution, it generally makes
> sense to run some simple reality checks on the number.  The numbers are a good
> length and it's common to make minor transcription errors when the card is not
> scanned directly.
>
> The first check people often do is to validate that the card matches a known
> pattern from one of the accepted card providers.  Some of these patterns are:
>
>         +============+=============+===============+
>         | Card Type  | Begins With | Number Length |
>         +============+=============+===============+
>         | AMEX       | 34 or 37    | 15            |
>         +------------+-------------+---------------+
>         | Discover   | 6011        | 16            |
>         +------------+-------------+---------------+
>         | MasterCard | 51-55       | 16            |
>         +------------+-------------+---------------+
>         | Visa       | 4           | 13 or 16      |
>         +------------+-------------+---------------+
>
> All of these card types also generate numbers such that they can be validated by
> the Luhn algorithm, so that's the second check systems usually try.  The steps
> are:
>
>         1. Starting with the next to last digit and continuing with every other
>            digit going back to the beginning of the card, double the digit
>         2. Sum all doubled and untouched digits in the number
>         3. If that total is a multiple of 10, the number is valid
>
> For example, given the card number 4408 0412 3456 7893:
>
>         Step 1:  8 4 0 8 0 4 2 2 6 4 10 6 14 8 18 3
>         Step 2:  8+4+0+8+0+4+2+2+6+4+1+0+6+1+4+8+1+8+3 = 70
>         Step 3:  70 % 10 == 0
>
> Thus that card is valid.
>
> Let's try one more, 4417 1234 5678 9112:
>
>         Step 1:  8 4 2 7 2 2 6 4 10 6 14 8 18 1 2 2
>         Step 2:  8+4+2+7+2+2+6+4+1+0+6+1+4+8+1+8+1+2+2 = 69
>         Step 3:  69 % 10 != 0
>
> That card is not valid.
>
> 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.

Here is my solution.
#!/usr/bin/ruby

credit_card_number = ARGV.join

case
when (credit_card_number=~/^(34|37)\d{13}$/): print 'AMEX '
when (credit_card_number=~/^6011\d{12}$/): print 'Discover '
when (credit_card_number=~/^5[1-5]\d{14}$/): print 'MasterCard '
when (credit_card_number=~/^4(\d{12}|\d{15})$/): print 'Visa '
else print 'Unknown '
end

i = 0
luhl_number = ''
credit_card_number.reverse.each_byte {|char|
  if (i%2==1) then
    char = (char.chr.to_i * 2).to_s
  else
    char = char.chr
  end
  luhl_number = char + luhl_number
  i += 1
}

sum_total = 0

luhl_number.each_byte {|char|
  sum_total += char.chr.to_i
}

if (sum_total%10==0) then
  print "Valid\n"
else
  print "Invalid\n"
end