How to Calculate a reference number with Ruby

Ruby posted almost 6 years ago by christian

This code can be used for calculating reference numbers. We inject a new method into the String and Fixnum classes that calculates the reference number for the corresponding string or fixnum:

   1  class InvalidReferenceNumber < StandardError
   2  end
   3  
   4  module ReferenceNumber
   5    def to_reference_number
   6      input = self  
   7      
   8      if(input.is_a? Fixnum)
   9        input = self.to_s
  10      end
  11      
  12      raise InvalidReferenceNumber, "Input should be between 3 to 19 characters long" if (input.length < 3 || input.length > 19)
  13      raise InvalidReferenceNumber, "Only spaces and numbers are allowed" if (input =~ /[^ \d]/) != nil
  14  
  15      input.gsub!(/ /, "")
  16      input.sub!(/0*/, "") # remove leading zeros
  17  
  18      raise InvalidReferenceNumber, "Input can't be just spaces and zeroes." if(input.length == 0)
  19  
  20      input.reverse!
  21      base = "731" * 50
  22      
  23      index = 0
  24      sum   = 0
  25  
  26      input.each_byte do |b|
  27        result = b.chr.to_i * base[index % 3].chr.to_i
  28        sum = sum + result
  29        index = index + 1
  30      end
  31      
  32      # Calculate the last number. If sum = 94 then number is 6.
  33      difference = (10 - (sum % 10)) % 10
  34  
  35      input = "#{difference}#{input}".reverse!
  36    end
  37  end
  38  
  39  class String
  40    include ReferenceNumber
  41  end
  42  
  43  class Fixnum
  44    include ReferenceNumber
  45  end

Example usage:

   1  "1111".to_reference_number
   2  1111.to_reference_number

The above example prints out “11112”.

This example shows how to generate a series of reference number:

   1  (1000..1023).to_a.each do |number|
   2    puts number.to_reference_number
   3  end

Here’s a unit test:

   1  class ReferenceNumberGeneratorTest < Test::Unit::TestCase
   2    def test_100_is_1009
   3      assert_equal "1009", "100".to_reference_number
   4    end
   5    def test_000100_is_1009
   6      assert_equal "1009", "000100".to_reference_number
   7    end
   8    def test_1000_is_10003
   9      assert_equal "10003", "1000".to_reference_number
  10    end
  11    def test_10000_is_100007
  12      assert_equal "100007", "10000".to_reference_number
  13    end
  14    def test_234_is_2341
  15      assert_equal "2341", "234".to_reference_number
  16    end
  17    def test_0234_is_2341
  18      assert_equal "2341", "0234".to_reference_number
  19    end
  20    def test_123123123234234234_is_1231231232342342349
  21      assert_equal "1231231232342342349", "123123123234234234".to_reference_number
  22    end
  23    def test_1000000000_is_10000000003
  24      assert_equal "10000000003", "1000000000".to_reference_number
  25    end
  26  end

Tagged referensnummer, viitenumero, reference number