[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Fwd: Please Forward: Ruby Quiz Submission

James Gray

4/29/2007 3:26:00 PM

Begin forwarded message:

> From: James Koppel <darmaniiii@yahoo.com>
> Date: April 27, 2007 7:53:31 PM CDT
> To: submission@rubyquiz.com
> Subject: Please Forward: Ruby Quiz Submission
>
> class Array
> def map_with_index
> each_with_index { |el, i|
> self[i] = yield el, i}
> end
> end
>
> #Contains the card types keyed by regular
> #expressions that match said card types
> $cardTypes = {/^3[47]\d{13}$/ => "AMEX",
> /^6011\d{12}$/ => "Discover",
> /^5[1-5]\d{14}$/ => "MasterCard",
> /^4\d{12}(\d{3})?$/ => "Visa"}
>
> #Returns the card type
> def cardType(cardNumber)
> $cardTypes.each_key {|format|
> return $cardTypes[format] if cardNumber =~ format}
> "Unknown"
> end
>
> require 'enumerator'
>
> #Returns whether it passes Luhn validation
> def luhn?(cardNumber)
> cardNumber.split(//).map_with_index do |el, i|
> #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
> #
> #This means that, if the length is even, even indices
> #are doubled, and vice versa
> if i % 2 == cardNumber.length % 2
> #Doubled digits will have to be split again
> (el.to_i * 2).to_s.split(//).map{|n| n.to_i}
> else
> el.to_i
> end
> #2) Sum all numbers
> end.flatten.enum_for.inject(0){|sum, num|sum + num } %
> #3)Check for multiple of 10
> 10 == 0
> end
>
> ARGV.each do |arg|
> puts cardType(arg)
> #1-line way of converting booleans to words
> puts ({false => "Invalid", true => "Valid"}[luhn?(arg)])
> end
>
> Ahhh...imagining that irresistible "new car" smell?
> Check out new cars at Yahoo! Autos.


1 Answer

James Barnett

4/29/2007 8:40:00 PM

0

Here's my solution:

#!/usr/bin/env ruby

def type(card)
if card =~ /\A4(\d{12}|\d{15})\Z/
"VISA"
elsif card =~ /\A3(4|7)\d{13}\Z/
"AMEX"
elsif card =~ /\A5[1-5]\d{14}\Z/
"MasterCard"
elsif card =~ /\A6011\d{12}\Z/
"Discover"
else
"Unknown"
end
end

def luhn_valid?(card)
digits = card.unpack("c#{card.length}").map { |c| c.chr.to_i }
sum = 0
digits.each_with_index do |n, i|
val = if i % 2 == digits.length % 2
2 * n
else
n
end

sum += if val >= 10
1 + (val % 10)
else
val
end
end
sum % 10 == 0
end

def valid?(card)
card_type = type(card)
puts "#{card_type} - #{ (card_type != "Unknown" && luhn_valid?
(card)) ? "Valid" : "Invalid" }"
end

valid?(ARGV[0])