Conversão de base 62

90

Como você converteria um número inteiro em base 62 (como hexadecimal, mas com estes dígitos: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ').

Tenho tentado encontrar uma boa biblioteca Python para ele, mas todos parecem estar ocupados com a conversão de strings. O módulo Python base64 aceita apenas strings e transforma um único dígito em quatro caracteres. Eu estava procurando por algo semelhante ao que os encurtadores de URL usam.

Mikl
fonte
Parece que alguém acabou de encontrar uma ideia para um projeto de código aberto :) Avise-me se encontrar algo ou decidir criar o seu próprio ...
samoz
Se você deseja criar URLs curtos, convém usar todo o conjunto de caracteres que não precisam ser codificados: en.wikipedia.org/wiki/Percent-encoding#Types_of_URI_characters . São 66 caracteres.
10b0
Acho que vou passar o ponto e o til, apenas para evitar a confusão do usuário, mas o travessão e os sublinhados devem valer a pena, obrigado.
mikl
que tal Base64? Você pode ter mais sorte em encontrar bibliotecas para isso.
Mike Cooper
Esta pergunta tem várias respostas aplicáveis: stackoverflow.com/questions/561486/…
Miles

Respostas:

166

Não existe um módulo padrão para isso, mas escrevi minhas próprias funções para fazer isso.

BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

def encode(num, alphabet):
    """Encode a positive number into Base X and return the string.

    Arguments:
    - `num`: The number to encode
    - `alphabet`: The alphabet to use for encoding
    """
    if num == 0:
        return alphabet[0]
    arr = []
    arr_append = arr.append  # Extract bound-method for faster access.
    _divmod = divmod  # Access to locals is faster.
    base = len(alphabet)
    while num:
        num, rem = _divmod(num, base)
        arr_append(alphabet[rem])
    arr.reverse()
    return ''.join(arr)

def decode(string, alphabet=BASE62):
    """Decode a Base X encoded string into the number

    Arguments:
    - `string`: The encoded string
    - `alphabet`: The alphabet to use for decoding
    """
    base = len(alphabet)
    strlen = len(string)
    num = 0

    idx = 0
    for char in string:
        power = (strlen - (idx + 1))
        num += alphabet.index(char) * (base ** power)
        idx += 1

    return num

Observe o fato de que você pode fornecer qualquer alfabeto para usar na codificação e decodificação. Se você deixar o alphabetargumento de fora, obterá o alfabeto de 62 caracteres definido na primeira linha do código e, portanto, a codificação / decodificação de / para a base 62.

Espero que isto ajude.

PS - Para encurtadores de URL, descobri que é melhor deixar alguns caracteres confusos como 0Ol1oI etc. Portanto, uso este alfabeto para minhas necessidades de encurtamento de URL - "23456789abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"

Diverta-se.

Baishampayan Ghose
fonte
5
+1: Legal! Isso pode ser estendido com mais caracteres compatíveis com URL para possivelmente salvar um caractere aqui e ali. Os personagens que eu sei que estão seguros são: $-_.+!*'(),;/?:@&= Você provavelmente pode usar alguns outros personagens também, como []~etc.
Blixt
24
Bug de nomenclatura: não tem base 62, já que o alfabeto é personalizável.
descontrair
3
Para a decodificação, é um hábito melhor não computar as potências (economiza tempo, é mais curto para escrever, mas mais importante evita erros off-by-one), assim: num = 0; para char na string: num = num * base + alphabet.index (char)
ShreevatsaR
1
@ShreevatsaR: algum motivo particular para usar str.index () em vez de uma pesquisa no dicionário? Veja minha resposta ...
John Machin,
2
Jonathan - pitão pode manipular números de comprimento arbitrário - não existe qualquer transbordamento: >>> * 256 (62 ** 100) 44402652562862911414971048359760030835982580330786570771137804709455598239929932673552190201125730101070867075377228748911717860448985185350731601887476350502973424822800696272224256L
Anthony Briggs
53

Uma vez escrevi um script para fazer isso também, acho que é bastante elegante :)

import string
# Remove the `_@` below for base62, now it has 64 characters
BASE_LIST = string.digits + string.letters + '_@'
BASE_DICT = dict((c, i) for i, c in enumerate(BASE_LIST))

def base_decode(string, reverse_base=BASE_DICT):
    length = len(reverse_base)
    ret = 0
    for i, c in enumerate(string[::-1]):
        ret += (length ** i) * reverse_base[c]

    return ret

def base_encode(integer, base=BASE_LIST):
    if integer == 0:
        return base[0]

    length = len(base)
    ret = ''
    while integer != 0:
        ret = base[integer % length] + ret
        integer /= length

    return ret

Exemplo de uso:

for i in range(100):                                    
    print i, base_decode(base_encode(i)), base_encode(i)
Wolph
fonte
9
Esta versão é consideravelmente mais rápida do que a solução aceita pela Baishampayan. Otimizei ainda mais calculando o comprimento fora da função. Resultados do teste (100.000 iterações): versão-WoLpH: .403 .399 .399 .398 .398 | versão-Baishampayan: 1.783 1.785 1.782 1.788 1.784. Esta versão é aproximadamente 4x mais rápida.
Jordânia,
se usar reversed(string)mais rápido do que fatiar string[::-1]na função base_decode.
ENDOH takanao
1
Levei muito tempo para encontrar esta questão. Nunca soube que isso era chamado de conversão de base62. Boa resposta.
Tive que mudar integer /= lengthpara integer //=lengthpara obter o resto correto
karlgold
10

O fabricante de decodificadores a seguir funciona com qualquer base razoável, tem um loop muito mais organizado e fornece uma mensagem de erro explícita quando encontra um caractere inválido.

def base_n_decoder(alphabet):
    """Return a decoder for a base-n encoded string
    Argument:
    - `alphabet`: The alphabet used for encoding
    """
    base = len(alphabet)
    char_value = dict(((c, v) for v, c in enumerate(alphabet)))
    def f(string):
        num = 0
        try:
            for char in string:
                num = num * base + char_value[char]
        except KeyError:
            raise ValueError('Unexpected character %r' % char)
        return num
    return f

if __name__ == "__main__":
    func = base_n_decoder('0123456789abcdef')
    for test in ('0', 'f', '2020', 'ffff', 'abqdef'):
        print test
        print func(test)
John Machin
fonte
Embora eu provavelmente nunca usasse isso, eu também lhe dei um sinal de positivo para criatividade. Este código me deu uma risada. :)
Sepero
@Sepero: O que é tão engraçado? É um software sério e robusto de força industrial. Sem Micky-Mouse invertendo com um **operador no loop.
John Machin de
Acalme-se amigo. Você está certo. Eu perdi a verdadeira bondade do seu loop interno devido a ele estar enterrado em coisas que não estão relacionadas com a pergunta (embrulho, verificação de erros, teste de unidade).
Sepero de
Parece bom, mas você não se esqueceu de um codificador de "força industrial" que usa um número inteiro mais o alfabeto para produzir uma string?
martineau de
1
O q no último valor foi intencional para mostrar o ValueError sendo gerado?
Thomas Vander Stichele
7

Se você está procurando a mais alta eficiência (como django), você vai querer algo como o seguinte. Este código é uma combinação de métodos eficientes de Baishampayan Ghose e WoLpH e John Machin.

# Edit this list of characters as desired.
BASE_ALPH = tuple("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_ALPH))
BASE_LEN = len(BASE_ALPH)

def base_decode(string):
    num = 0
    for char in string:
        num = num * BASE_LEN + BASE_DICT[char]
    return num

def base_encode(num):
    if not num:
        return BASE_ALPH[0]

    encoding = ""
    while num:
        num, rem = divmod(num, BASE_LEN)
        encoding = BASE_ALPH[rem] + encoding
    return encoding

Você também pode calcular o seu dicionário com antecedência. (Observação: a codificação com uma string mostra mais eficiência do que com uma lista, mesmo com números muito longos.)

>>> timeit.timeit("for i in xrange(1000000): base.base_decode(base.base_encode(i))", setup="import base", number=1)
2.3302059173583984

Codificou e decodificou 1 milhão de números em menos de 2,5 segundos. (2,2 Ghz i7-2670QM)

Sepero
fonte
Não é necessário necessariamente ao tuple()redor BASE_ALPHno início. Em Python, cada String é iterável. Esse recurso é explorado por enumerate(). Então o código fica ainda mais enxuto :)
Luis Nell
6
Ei origiNell, você está certo de que a tupla () não é necessária, mas no meu sistema, ela faz o código rodar cerca de 20% mais rápido. Experimente testá-lo sem a tupla () e veja o que funciona melhor para você. Saúde :)
Sepero
Ponto interessante. Faz todo o sentido, pois as tuplas são mais leves do que as strings. Obrigado pela iluminação :)!
Luis Nell,
@Sepero I melhorou ainda mais sua versão em termos de formatação, nomenclatura, testes e funcionalidade (números negativos são suportados): pastebin.com/4uket7iu (você pode atualizar sua resposta com isto)
Joschua
@Joschua - Seu código em sua URL não funcionou para mim. base_encode () parecia gerar apenas um dígito codificado para os números que testei.
SMGreenfield
4

Se você usar o framework django, você pode usar o módulo django.utils.baseconv.

>>> from django.utils import baseconv
>>> baseconv.base62.encode(1234567890)
1LY7VK

Além de base62, o baseconv também definiu base2 / base16 / base36 / base56 / base64.

Ryan Fau
fonte
3

Você provavelmente deseja base64, não base62. Há uma versão compatível com URL dele circulando, então os dois caracteres de preenchimento extras não devem ser um problema.

O processo é bastante simples; considere que base64 representa 6 bits e um byte regular representa 8. Atribua um valor de 000000 a 111111 a cada um dos 64 caracteres escolhidos e coloque os 4 valores juntos para corresponder a um conjunto de 3 bytes base256. Repita para cada conjunto de 3 bytes, preenchendo no final com sua escolha de caractere de preenchimento (0 geralmente é útil).

Williham Totland
fonte
5
Os métodos de codificação Python base64 padrão não são realmente adequados para URLs curtos, uma vez que são otimizados para codificar bytes (ou seja, strings / letras) e produzirão saídas mais longas do que apenas o deslocamento de base do valor numérico.
mikl,
@mikl Claro, o módulo base64 do Python pode não ser adequado para gerar URLs curtos, mas todos os métodos de codificação do Python funcionam realmente em sequências numéricas de base 256. bytes são realmente "strings" codificadas em base 256. Python 2.x trata strings como uma seqüência de bytes, enquanto Python 3.x (que faz a coisa certa) trata strings como Unicode. Portanto, b'foobar 'é realmente apenas uma maneira elegante de escrever [102, 111, 111, 98, 97, 114] ou [0x66,0x6f, 0x6f, 0x62,0x61,0x72] ou b' \ x66 \ x6f \ x6f \ x62 \ x61 \ x72 'que, sem surpresa, é a representação de base 256. Bytes não são strings ou letras. Bytes são bytes. =)
yesudeep de
@yesudeep: Então, bytes são bytes ... e qual é exatamente o seu ponto?
martineau de
3

Se tudo o que você precisa é gerar um ID curto (já que você mencionou encurtadores de URL) em vez de codificar / decodificar algo, este módulo pode ajudar:

https://github.com/stochastic-technologies/shortuuid/

Stavros Korokithakis
fonte
Não tenho certeza se isso é apropriado para URLs curtos. Um UUID é geralmente um número muito grande, então mesmo a codificação base57 como ele faz é obrigado a ser bastante longo para uma URL curta.
Mikl
Você pode cortar o quanto quiser, as colisões ainda serão improváveis, pois é puramente aleatório, mas não será mais um id único.
Stavros Korokithakis
2

você pode baixar o módulo zbase62 de pypi

por exemplo

>>> import zbase62
>>> zbase62.b2a("abcd")
'1mZPsa'
ghostdog74
fonte
2
Sim, eu olhei isso antes, mas ele converte strings, não números :)
mikl
2

Eu me beneficiei muito das postagens de outros aqui. Eu precisava do código python originalmente para um projeto Django, mas desde então eu mudei para node.js, então aqui está uma versão javascript do código (a parte de codificação) que Baishampayan Ghose forneceu.

var ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

function base62_encode(n, alpha) {
  var num = n || 0;
  var alphabet = alpha || ALPHABET;

  if (num == 0) return alphabet[0];
  var arr = [];
  var base = alphabet.length;

  while(num) {
    rem = num % base;
    num = (num - rem)/base;
    arr.push(alphabet.substring(rem,rem+1));
  }

  return arr.reverse().join('');
}

console.log(base62_encode(2390687438976, "123456789ABCDEFGHIJKLMNPQRSTUVWXYZ"));
Stephen
fonte
Eu atualizei este código e o transformei em um projeto de código aberto para qualquer pessoa interessada github.com/sbussard/encode-the-things
Stephen
2

Espero que o seguinte snippet possa ajudar.

def num2sym(num, sym, join_symbol=''):
    if num == 0:
        return sym[0]
    if num < 0 or type(num) not in (int, long):
        raise ValueError('num must be positive integer')

    l = len(sym)  # target number base
    r = []
    div = num
    while div != 0: # base conversion
        div, mod = divmod(div, l)
        r.append(sym[mod])

    return join_symbol.join([x for x in reversed(r)])

Uso para o seu caso:

number = 367891
alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
print num2sym(number, alphabet)  # will print '1xHJ'

Obviamente, você pode especificar outro alfabeto, consistindo em um número maior ou menor de símbolos, então ele converterá seu número para a base numérica menor ou maior. Por exemplo, fornecer '01' como um alfabeto produzirá uma string que representa o número de entrada como binário.

Você pode embaralhar o alfabeto inicialmente para ter uma representação única dos números. Pode ser útil se você estiver fazendo um serviço de encurtador de URL.

Vladimir Ignatyev
fonte
1
Não é ruim. Você pode querer usar if num < 0 or type(num) not in (int, long):.
martineau
Assim é melhor, mas é um pouco mais complicado porque longnão existe no Py 3.x - então, pode-se querer usar esta resposta .
martineau
1
Ou usar a minha própria versão portátil: isinstance(x, (type(1), type(2**32))).
martineau
2

Agora existe uma biblioteca python para isso.

Estou trabalhando em fazer um pacote pip para isso.

Eu recomendo que você use meu bases.py https://github.com/kamijoutouma/bases.py que foi inspirado em bases.js

from bases import Bases
bases = Bases()

bases.toBase16(200)                // => 'c8'
bases.toBase(200, 16)              // => 'c8'
bases.toBase62(99999)              // => 'q0T'
bases.toBase(200, 62)              // => 'q0T'
bases.toAlphabet(300, 'aAbBcC')    // => 'Abba'

bases.fromBase16('c8')               // => 200
bases.fromBase('c8', 16)             // => 200
bases.fromBase62('q0T')              // => 99999
bases.fromBase('q0T', 62)            // => 99999
bases.fromAlphabet('Abba', 'aAbBcC') // => 300

consulte https://github.com/kamijoutouma/bases.py#known-basesalphabets para saber quais bases são utilizáveis

Belldandu
fonte
2

Esta é minha solução:

def base62(a):
    baseit = (lambda a=a, b=62: (not a) and '0' or
        baseit(a-a%b, b*62) + '0123456789abcdefghijklmnopqrstuvwxyz'
                              'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[a%b%61 or -1*bool(a%b)])
    return baseit()

explicação

Em qualquer base, cada número é igual a a1+a2*base**2+a3*base**3...Portanto, o objetivo é encontrar todos os as.

Para cada N=1,2,3...código isola o aN*base**Npor "moduloing" por bpara b=base**(N+1)que corta todo aé maior do que N, e cortando todo o aé de modo que sua série é menor do que Ndiminuindo acada vez que a função é chamada de forma recursiva pela corrente aN*base**N.

Base%(base-1)==1portanto base**p%(base-1)==1e, portanto, q*base^p%(base-1)==qcom apenas uma exceção, quando q==base-1que retorna 0. Para consertar esse caso, ele retorna 0. A função verifica 0desde o início.


vantagens

Neste exemplo, há apenas uma multiplicação (em vez de uma divisão) e algumas operações de módulo, que são todas relativamente rápidas.

Shu ba
fonte
1

Pessoalmente, gosto da solução de Baishampayan, principalmente por despir os personagens confusos.

Para integridade e solução com melhor desempenho, este post mostra uma forma de usar o módulo Python base64.

Van Gale
fonte
1
Como mencionei em meu comentário a Williham Totland, Pythons base64 é subótimo para números de codificação, uma vez que é otimizado para strings.
mikl,
1

Escrevi isso há um tempo e funcionou muito bem (negativos e todos incluídos)

def code(number,base):
    try:
        int(number),int(base)
    except ValueError:
        raise ValueError('code(number,base): number and base must be in base10')
    else:
        number,base = int(number),int(base)
    if base < 2:
        base = 2
    if base > 62:
        base = 62
    numbers = [0,1,2,3,4,5,6,7,8,9,"a","b","c","d","e","f","g","h","i","j",
               "k","l","m","n","o","p","q","r","s","t","u","v","w","x","y",
               "z","A","B","C","D","E","F","G","H","I","J","K","L","M","N",
               "O","P","Q","R","S","T","U","V","W","X","Y","Z"]
    final = ""
    loc = 0
    if number < 0:
        final = "-"
        number = abs(number)
    while base**loc <= number:
        loc = loc + 1
    for x in range(loc-1,-1,-1):
        for y in range(base-1,-1,-1):
            if y*(base**x) <= number:
                final = "{}{}".format(final,numbers[y])
                number = number - y*(base**x)
                break
    return final

def decode(number,base):
    try:
        int(base)
    except ValueError:
        raise ValueError('decode(value,base): base must be in base10')
    else:
        base = int(base)
    number = str(number)
    if base < 2:
        base = 2
    if base > 62:
        base = 62
    numbers = ["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f",
               "g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v",
               "w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L",
               "M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
    final = 0
    if number.startswith("-"):
        neg = True
        number = list(number)
        del(number[0])
        temp = number
        number = ""
        for x in temp:
            number = "{}{}".format(number,x)
    else:
        neg = False
    loc = len(number)-1
    number = str(number)
    for x in number:
        if numbers.index(x) > base:
            raise ValueError('{} is out of base{} range'.format(x,str(base)))
        final = final+(numbers.index(x)*(base**loc))
        loc = loc - 1
    if neg:
        return -final
    else:
        return final

desculpe pela duração de tudo

Thropian
fonte
1
BASE_LIST = tuple("23456789ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz")
BASE_DICT = dict((c, v) for v, c in enumerate(BASE_LIST))
BASE_LEN = len(BASE_LIST)

def nice_decode(str):
    num = 0
    for char in str[::-1]:
        num = num * BASE_LEN + BASE_DICT[char]
    return num

def nice_encode(num):
    if not num:
        return BASE_LIST[0]

    encoding = ""
    while num:
        num, rem = divmod(num, BASE_LEN)
        encoding += BASE_LIST[rem]
    return encoding
paulkav1
fonte
1
Isso corrige o nome de BASE_LIST e também inverte a string na decodificação que foi omitida na resposta excelente de Spero
paulkav1
1

Aqui está uma maneira recorrente e iterativa de fazer isso. O iterativo é um pouco mais rápido dependendo da contagem de execução.

def base62_encode_r(dec):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    return s[dec] if dec < 62 else base62_encode_r(dec / 62) + s[dec % 62]
print base62_encode_r(2347878234)

def base62_encode_i(dec):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ret = ''
    while dec > 0:
        ret = s[dec % 62] + ret
        dec /= 62
    return ret
print base62_encode_i(2347878234)

def base62_decode_r(b62):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    if len(b62) == 1:
        return s.index(b62)
    x = base62_decode_r(b62[:-1]) * 62 + s.index(b62[-1:]) % 62
    return x
print base62_decode_r("2yTsnM")

def base62_decode_i(b62):
    s = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    ret = 0
    for i in xrange(len(b62)-1,-1,-1):
        ret = ret + s.index(b62[i]) * (62**(len(b62)-i-1))
    return ret
print base62_decode_i("2yTsnM")

if __name__ == '__main__':
    import timeit
    print(timeit.timeit(stmt="base62_encode_r(2347878234)", setup="from __main__ import base62_encode_r", number=100000))
    print(timeit.timeit(stmt="base62_encode_i(2347878234)", setup="from __main__ import base62_encode_i", number=100000))
    print(timeit.timeit(stmt="base62_decode_r('2yTsnM')", setup="from __main__ import base62_decode_r", number=100000))
    print(timeit.timeit(stmt="base62_decode_i('2yTsnM')", setup="from __main__ import base62_decode_i", number=100000))

0.270266867033
0.260915645986
0.344734796766
0.311662500262
Wenzul
fonte
Gostei muito da sua abordagem recursiva. Minha filha, que estava fazendo AP Comp Sci, descobriu essa mesma solução para eu implementar uma "base25" (usando 'ABCDEFHJKMNPQRTUVWXY34789') em C ++. Fui convertê-lo para Python e ser um newb total com essa linguagem encontrei alguns obstáculos - que você resolveu elegantemente em uma única linha de código! Você até evita um problema comum com 0 traduzindo para uma string vazia em alfabetos que não começam com 0-9. Ótimo trabalho! (Não preciso de números negativos, mas sua abordagem foi tão boa que seria bom adicioná-lo para navegadores futuros)
SMGreenfield
1

Pitão 3.7.x

Encontrei um github de PhD para alguns algoritmos ao procurar um script base62 existente . Não funcionou para a versão max atual do Python 3 neste momento, então fui em frente e consertei onde necessário e fiz uma pequena refatoração. Eu normalmente não trabalho com Python e sempre usei ad-hoc, então YMMV. Todo o crédito vai para o Dr. Zhihua Lai . Acabei de resolver os problemas desta versão do Python.

Arquivo base62.py

#modified from Dr. Zhihua Lai's original on GitHub
from math import floor
base = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
b = 62;
def toBase10(b62: str) -> int:
    limit = len(b62)
    res = 0
    for i in range(limit):
        res = b * res + base.find(b62[i])
    return res
def toBase62(b10: int) -> str:
    if b <= 0 or b > 62:
        return 0
    r = b10 % b
    res = base[r];
    q = floor(b10 / b)
    while q:
        r = q % b
        q = floor(q / b)
        res = base[int(r)] + res
    return res

Arquivo try_base62.py

import base62
print("Base10 ==> Base62")
for i in range(999):
    print(f'{i} => {base62.toBase62(i)}')
base62_samples = ["gud", "GA", "mE", "lo", "lz", "OMFGWTFLMFAOENCODING"]
print("Base62 ==> Base10")
for i in range(len(base62_samples)):
    print(f'{base62_samples[i]} => {base62.toBase10(base62_samples[i])}')

saída de try_base62.py

Base10 ==> Base62
0 => 0
[...]
998 => g6
Base62 ==> Base10
gud => 63377
GA => 2640
mE => 1404
lo => 1326
lz => 1337
OMFGWTFLMFAOENCODING => 577002768656147353068189971419611424

Como não havia informações de licenciamento no repo, eu enviei um PR para que o autor original pelo menos saiba que outras pessoas estão usando e modificando seu código.

kayleeFrye_onDeck
fonte
0

Não posso ajudá-lo com uma biblioteca aqui. Eu preferiria usar base64 e apenas adicionar caracteres extras à sua escolha - se possível!

Então você pode usar o módulo base64.

Se isso for realmente impossível:

Você pode fazer isso sozinho (este é um pseudocódigo):

base62vals = []
myBase = 62
while num > 0:
   reminder = num % myBase
   num = num / myBase
   base62vals.insert(0, reminder)
Juergen
fonte
0

com recursão simples

"""
This module contains functions to transform a number to string and vice-versa
"""
BASE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
LEN_BASE = len(BASE)


def encode(num):
    """
    This function encodes the given number into alpha numeric string
    """

    if num < LEN_BASE:
        return BASE[num]

    return BASE[num % LEN_BASE] + encode(num//LEN_BASE)


def decode_recursive(string, index):
    """
    recursive util function for decode
    """

    if not string or index >= len(string):
        return 0

    return (BASE.index(string[index]) * LEN_BASE ** index) + decode_recursive(string, index + 1)


def decode(string):
    """
    This function decodes given string to number
    """

    return decode_recursive(string, 0)
Lokesh Sanapalli
fonte
0

Mais simples de todos.

BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
def encode_base62(num):
    s = ""
    while num>0:
      num,r = divmod(num,62)
      s = BASE62[r]+s
    return s


def decode_base62(num):
   x,s = 1,0
   for i in range(len(num)-1,-1,-1):
      s = int(BASE62.index(num[i])) *x + s
      x*=62
   return s

print(encode_base62(123))
print(decode_base62("1Z"))
Melvil James
fonte