Skip to content

Instantly share code, notes, and snippets.

@yinian1992
Last active December 21, 2015 16:28
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 yinian1992/6333736 to your computer and use it in GitHub Desktop.
Save yinian1992/6333736 to your computer and use it in GitHub Desktop.
Base56 Unique ID Generator
# Porting from http://blog.kevburnsjr.com/php-unique-hash
# and modified some codes to support variable length
# Min length of unique id
MIN_LENGTH = 2
# Unique ID contains some of these 56 chars
CHARSET = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789'
# Some primes greater than 56 ^ n / 1.61803398874989484
PRIMES = (1, 41, 2377, 147299, 9132313, 566201239, 35104476161, 2176477521929,
134941606358731, 8366379594239857, 518715534842869223)
# Modular multiplicative inverses of the primes above a modulo 56 ^ n
PRIME_MMIS = (0, 41, 1913, 138827, 8332073, 245539879, 30024414209,
1027858277945, 218295060195, 4497555361599889,
110048532750208471)
def base56_encode(num):
encoded = ""
while num > 0:
mod = num % 56
encoded += CHARSET[mod]
num = num / 56
return encoded
def base56_decode(encoded):
num = 0
i = 0
for char in encoded:
dec = CHARSET.index(char)
num += dec * 56 ** i
i += 1
return num
def mmi_hash(num):
length = 0
for order in xrange(len(PRIMES)):
length = order
if num < 56 ** order:
break
if length < MIN_LENGTH:
length = MIN_LENGTH
ceil = pow(56, length)
dec = (num * PRIMES[length]) % ceil
return base56_encode(dec).zfill(length)
def mmi_unhash(hash):
ceil = pow(56, len(hash))
num = base56_decode(hash.strip('0'))
dec = (num * PRIME_MMIS[len(hash)]) % ceil
return dec
# testing
if __name__ == '__main__':
import random
rand_num = random.randint(1, 56**10)
assert rand_num == mmi_unhash(mmi_hash(rand_num))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment