Created
March 27, 2011 18:03
-
-
Save sergeych/889423 to your computer and use it in GitHub Desktop.
The user-readable huge number encoder that corrects misreadings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
## | |
# The arbitrary-length positive integers to human readable form codec (serials, links and like). | |
# The idea is to avoid misreading/misinterpetation of symbols. For example, | |
# the letter 0 o and O, ir I and 1, often looks very likely. The numcode | |
# takes care of it using clearly distinctive characters for both English and Russian | |
# charset and corrects potential errors | |
# | |
# Numcode uses set 21 characters common to Russian and English to encode positive decimal | |
# integer numbers of arbitrary size. Characters and digits are chosen in a way | |
# to reduce the risk oh misreading it (ABEKMHOPCTYX123456789). Resulting word | |
# can be separated by '-' (default) or any of ' =./:' to ease reading. | |
# | |
class Numcode | |
class Error < StandardError; end | |
@@digits = ["ABEKMHOPCTYX123456789","АВЕКМНОРСТУХI", "АВЕКМН0"] | |
def self.encode x, delimiter='-' | |
value = x.to_i | |
raise Error, "Should be integer number: #{x}" if x != value | |
res = '' | |
digs = @@digits[0] | |
n = -1 | |
begin | |
res << delimiter if (n += 1) > 1 && n % 5 == 0 | |
value,r = value.divmod(21) | |
res << digs[r] | |
end while value > 0 | |
res | |
end | |
# Correct key, substitute alike characters (0 for O) including | |
# language (Rusian/English) misunderstanging and decode value | |
def self.decode str | |
value = 0 | |
k = 1 | |
str.upcase.each_char do |c| | |
next if '-=./: '.include? c | |
n = nil | |
@@digits.each { |set| | |
n = set.index(c) | |
break if n | |
} | |
raise Error, "Bad characted in numcode #{str.inspect}" unless n | |
value += n * k | |
k *= 21 | |
end | |
value | |
end | |
def self.test | |
77134.times { |i| | |
x = decode(encode(i)) | |
raise "#{i} -> #{x}" unless x == i | |
} | |
end | |
## Create random Numcode of len characters not including | |
# separators | |
def self.random len=15, delimiter = '-' | |
dd = @@digits[0] | |
n = -1 | |
res = '' | |
while (len-=1) >= 0 | |
res << delimiter if (n += 1) > 1 && n % 5 == 0 | |
res << dd[rand 21] | |
end | |
res | |
end | |
def self.guid | |
random_code 15, '-' | |
end | |
end | |
class Numeric | |
def to_numcode delimiter='-' | |
Numcode.encode(self,delimiter) | |
end | |
end | |
class String | |
def decode_numcode | |
Numcode.decode self | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment