Write a program that checks if a given string is a valid credit card number.
Credit card numbers have a checksum embedded in them, so not every sequence of digits is valid. The checksum is calculated by using the Luhn algorithm and is stored as the last digit. The algorithm has the following steps:
If we were to apply the algorithm to 4539 1488 0343 6467
, the steps would produce the following results:
8 5 6 9 2 4 16 8 0 3 8 3 12 4 12 7
8 5 6 9 2 4 7 8 0 3 8 3 3 4 3 7
8+5+6+9+2+4+7+8+0+3+8+3+3+4+3+7 = 80
. It is a multiple of 10, so the credit
card number is valid.Credit card numbers will be passed to your program as strings containing digits and optional spaces. Although most credit card numbers have 16 digits, don’t count on it – credit card numbers could have anywhere from 8 to 19 digits, so your program has to be able to handle numbers of arbitrary length.
Example:
credit_card_number_valid? '4539 1488 0343 6467' # => true credit_card_number_valid? '4539 1488 0343 6462' # => false credit_card_number_valid? '799 27398 713' # => true
The lower the score - the better. It is the shortest solution that wins.
Rank: 1
Nickname: ssk
Score: 94
def credit_card_number_valid? s r = 0 q = 1 s.reverse.scan(/\d/) { r += (_ = $&.to_i * q) % 10 + _ / 10 q ^= 3 } r % 10 < 1 end
Rank: 2
Nickname: vizvamitra
Score: 105
def self.method_missing _,s r=0 s.tr!(' ',% ).size.times{ |i| d = s[-i-1].to_i r += [d,d%5*2+(d>4?1:0)][i%2] } r % 10 < 1 end
Rank: 3
Nickname: Gosho337
Score: 108
def credit_card_number_valid? c a=0 for x, y in c.reverse.scan /(\d) *(\d?)/ a+=x.to_i + (y==?9 ? 9 : y.to_i*2%9) end a%10<1 end
Rank: 4
Nickname: meerkat
Score: 109
def credit_card_number_valid? n s = 0 n.split(/ */).reverse.each_slice(2) { |i, j| s += i.to_i + (k = j.to_i * 2) + k / 10 } s % 10 < 1 end
Rank: 5
Nickname: Sve
Score: 112
def credit_card_number_valid? s a = s.scan /\d/ r = 0 f = a.size.odd? a.each { |e| f = !f e = e.to_i r+= f ? e < 5 ? e * 2 : e * 2 % 10 + 1 : e } r % 10 < 1 end
Rank: 6
Nickname: halfbyte
Score: 113
def credit_card_number_valid? n s=0 d=p n.reverse.each_byte {|c| s+= (c-=48)<0 ? 0: ((d=!d) ? c : (x=(c * 2)) % 10 + (x / 10)) } s % 10 < 1 end
Rank: 7
Nickname: mykhi
Score: 114
def credit_card_number_valid?(s) a=s.scan(/\d/) l=a.size a.map{|k|(i=k.to_i*((l-=1)%2+1))%10+i/10}.inject(:+)%10==0 end
Rank: 7
Nickname: mbd
Score: 114
def credit_card_number_valid? s t = 0 s.scan(/\d/).reverse.each_slice(2).map { |x, y| t += x.to_i + (z = y.to_i * 2) + z / 10 } t % 10 == 0 end
Rank: 9
Nickname: rmosolgo
Score: 115
def credit_card_number_valid?(n) c = 0 i = -1 n.reverse.scan(/\d/) do c += ((t =($&.to_i * ((i += 1) % 2 < 1 ? 1 : 2))) % 10 ) + t / 10 end c % 10 < 1 end
Rank: 10
Nickname: bohos
Score: 116
def credit_card_number_valid? s s = s.tr(' ', '').chars u = s.size s.inject(0) { |m,x| l = x.to_i * ((u -= 1) % 2 + 1); m + l%10 + l/10 } % 10 == 0 end
Rank: 11
Nickname: svetlio
Score: 118
def credit_card_number_valid? s l = -> a, b { n = a % 10 a != 0 ? (b ? n > 4 ? 1 + 2 * n % 10 : 2 * n : n) + l[a / 10, !b] : 0 } l[s.tr(' ', '').to_i, false] % 10 == 0 end
Rank: 12
Nickname: ivan
Score: 145
def credit_card_number_valid?(sequence) s = 0 sequence.delete(' ').reverse.split('').each_with_index do |c, i| s += t = (2 ** (i % 2)) * c.to_i s -= 9 if t > 9 end s % 10 == 0 end
Rank: 13
Nickname: rb-bikezilla
Score: 151
def credit_card_number_valid?(s) x = -> (a, o, r = []){ c = a.pop d = c*2 r<<(o ? c : d < 9 ? d : d-9) a==[] ? r : x.(a, !o, r) } x.(s.tr(' ','').chars.map(&:to_i), '').reduce(:+)%10==0 end
Rank: 14
Nickname: Jure
Score: 162
def credit_card_number_valid? s s.gsub(/ /, '').chars.reverse.map.with_index { |c, i| i % 2 < 1 ? c.to_i : (c.to_i * 2).to_s.scan(/\d/).map(&:to_i).reduce(&:+) }.reduce(&:+) % 10 == 0 end