Search code examples
ruby

Implementing the Luhn validation algorithm in Ruby


I've been trying to implement the Luhn algorithm in Ruby. I've been following these steps:

  • The formula verifies a number against its included check digit, which is usually appended to a partial account number to generate the full account number. This account number must pass the following test:
    • Counting from the check digit, which is the rightmost, and moving left, double the value of every second digit.
    • Sum the digits of the products (e.g., 10 = 1 + 0 = 1, 14 = 1 + 4 = 5) together with the undoubled digits from the original number.
    • If the total modulo 10 is equal to 0 (if the total ends in zero) then the number is valid according to the Luhn formula; else it is not valid.

http://en.wikipedia.org/wiki/Luhn_algorithm

This is what I've came up with:

 def validCreditCard(cardNumber)
    sum = 0
    nums = cardNumber.to_s.split("")
    nums.insert(nums.size, "x")
    nums.reverse!
    nums.each_with_index do |n, i|
        if !n.eql?("x")
            sum += (i % 2 == 0) ? n.to_i : n.to_i * 2
        end
    end
    if (sum % 10) == 0
        return true
    else
        return false
    end
end

However, this returns false every time I test it. I am not sure what I am doing wrong.


Solution

  • Here's a quick one that works:

    def credit_card_valid?(account_number)
      digits = account_number.chars.map(&:to_i)
      check = digits.pop
    
      sum = digits.reverse.each_slice(2).flat_map do |x, y|
        [(x * 2).divmod(10), y || 0]
      end.flatten.inject(:+)
    
      check.zero? ? sum % 10 == 0 : (10 - sum % 10) == check
    end
    
    credit_card_valid? "79927398713" #=> true
    credit_card_valid? "79927398714" #=> false