Receipt Bank Logo + Balkan Ruby Logo

Credit card numbers verifier

Credit card numbers verifier

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:

  1. From the rightmost digit, which is the checksum digit, and moving left, double the value of every second digit. The check digit is not doubled, the first digit doubled is immediately to the left of the check digit.
  2. If the result of the doubling operation from the previous step is greater than 9, then add the digits of the product in order to obtain a single-digit value.
  3. Add the resulting altered digits together. If the sum is a multiple of 10, the original number is a valid credit card number.

If we were to apply the algorithm to 4539 1488 0343 6467, the steps would produce the following results:

  1. After step one, we have 8 5 6 9 2 4 16 8 0 3 8 3 12 4 12 7
  2. After step two, we have 8 5 6 9 2 4 7 8 0 3 8 3 3 4 3 7
  3. The checksum after step 3 is 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

Leader board

The lower the score - the better. It is the shortest solution that wins.

If you're ranked in the first 10, stop by our booth to claim your reward.
Winner!

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
Winner!

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
Winner!

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
Winner!

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
Winner!

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
Winner!

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
Winner!

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
Winner!

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
Winner!

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
Winner!

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