import hashlib


enc_table_16 = "0123456789abcdef"
enc_table_64 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"


def int_to_enc(n, enc_table):
    """Encode integer into string, using digit encoding table.

    You can encode integer into hexadecimal string:

    >>> int_to_enc(20190925, enc_table_16)
    '13416cd'

    To verify use, python's hex() function:

    >>> hex(20190925)
    '0x13416cd'

    You can encode integer using 64 digit table:

    >>> int_to_enc(20190925, enc_table_64)
    '1d1rd'

    """
    if n == 0:
        return enc_table[0]

    base = len(enc_table)
    digits = ""
    while n:
        digits += enc_table[int(n % base)]
        n //= base
    return digits[::-1]


def short_str_enc(s, char_length=8, enc_table=enc_table_64):
    """Geneate string hash with given length, using specified encoding table.

    Example 1:

    Generating hash with length of 8 characters, using hexadecimal encoding table:

    >>> short_str_enc("hello world", 8, enc_table_16)
    '309ecc48'

    Generating hash with length of 8 charactes, using extended 64-digit encoding table:

    >>> short_str_enc("hello world", 8, enc_table_64)
    'MDIN8D1b'
    """

    if char_length > 128:
        raise ValueError("char_length {} exceeds 128".format(char_length))
    hash_object = hashlib.sha512(s.encode())
    hash_hex = hash_object.hexdigest()
    hash_enc = int_to_enc(int(hash_hex, 16), enc_table)
    return hash_enc[0:char_length]
