Skip to content

Instantly share code, notes, and snippets.

@zmalltalker
Created January 31, 2019 14:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zmalltalker/ebf5078b2fca73ce16b94df0c03faac5 to your computer and use it in GitHub Desktop.
Save zmalltalker/ebf5078b2fca73ce16b94df0c03faac5 to your computer and use it in GitHub Desktop.
class NorwegianBankAccount
# Pass me any kind of string representing an account number
def initialize(str)
@numbers = str.gsub(/[^\d]/,'')
end
# Prettified output
def to_s
begin
parts = @numbers.split(//)
formatted = [parts[0,4].join(""), parts[4,2].join(""), parts[6,5].join("")].join(".")
formatted
rescue => e
"##{self.class.name}<#{@numbers}> (#{e})"
end
end
# Validation combo. Using a tuple as return value, in true Golang fashion
def valid?
if @numbers.length != 11
return false, "Needs to be 11 digits"
end
if !mod_11_control(@numbers, [5,4,3,2,7,6,5,4,3,2])
return false, "Invalid checksum"
end
return true, nil
end
# Validate an account number using mod 11 with multiplication factors.
# Includes check digit for simplicity (ie 11 digits as input)
def mod_11_control(account_number, factors)
account_parts = account_number.split(//)
account_digits = account_parts[0,10].map(&:to_i)
sum = 0
account_digits.each_with_index do |n, i|
s = n * factors[i]
sum += (n * factors[i])
end
check_digit = account_parts[10].to_i
remainder = sum % 11
expected_check_digit = case remainder
when 0 then remainder
when 1 then nil
else 11- remainder
end
return check_digit == expected_check_digit
end
end
# Unittest built in, skip for production
require 'minitest/autorun'
class NorwegianBankAccountTest < Minitest::Test
def test_invalid_length
@v = NorwegianBankAccount.new("1234.56.789")
valid, message = @v.valid?
refute valid, "#{@v} has an incorrect length"
end
def test_invalid_checksum
@v = NorwegianBankAccount.new("1234.56.78901")
valid, message = @v.valid?
refute valid, "#{@v} has an incorrect checksum"
end
def test_valid_account_number
@v = NorwegianBankAccount.new("1299.14.91285")
valid, message = @v.valid?
assert valid, "#{@v} should be a valid account number"
end
def test_crazy_input
@v = NorwegianBankAccount.new("Morten Bankebiff")
valid, message = @v.valid?
refute valid, "#{@v} is wrong in so many ways"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment