Skip to content

Instantly share code, notes, and snippets.

@sergeych
Created March 27, 2011 18:03
Show Gist options
  • Save sergeych/889423 to your computer and use it in GitHub Desktop.
Save sergeych/889423 to your computer and use it in GitHub Desktop.
The user-readable huge number encoder that corrects misreadings
# 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