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
