2 votes

Python: Code chaîne en une chaîne plus courte et sans signification de manière réversible

Désolé pour la question générique (je n'ai aucune connaissance préalable sur la compression et je ne sais pas s'il existe une solution possible).

J'ai des codes toujours composés de 19 caractères.

Ces caractères ne peuvent être que : A-Z, a-z, 0-9, ., :, -

Un exemple pourrait être quelque chose comme 1995AbC...123..456Z

Ce que je veux faire, c'est trouver un moyen de convertir de manière réversible cette chaîne en une chaîne plus courte qui ne contient que des caractères ascii : quelque chose comme gfSDd2H.

  • Est-ce possible ?
  • Y a-t-il un moyen de le faire en python ?

Merci !

5voto

Mark Byers Points 318575

Vous pouvez essayer de compresser la chaîne puis encoder le résultat par exemple en base64. Cela suppose bien sûr que vos chaînes originales soient compressibles. Pour des chaînes de 19 caractères, cela semble peu probable.

Si vous êtes autorisé à conserver certaines données, vous pouvez compresser la première chaîne en 1, la deuxième en 2, etc... et vous devrez stocker la correspondance que vous avez faite dans par exemple une base de données afin de pouvoir la inverser. Vous pouvez ensuite encoder le nombre en une chaîne en base 64 (ou une autre base).

C'est similaire à la façon dont fonctionnent les services de raccourcissement d'URL.

4voto

phihag Points 89765

Vous autorisez 65 caractères différents. En supposant que toutes les entrées ont la même probabilité, chaque encodage produirait au moins 19*65/128 ≈ 10 caractères. Cependant, étant donné que vous voulez probablement ignorer les caractères non imprimables, cela est réduit à 19*65/95=13 caractères avec une correspondance parfaite. Par conséquent, tout mapping de ce type ne conduira pas à une réduction significative de l'espace.

2voto

John Machin Points 39706

Bien sûr, c'est possible en Python. Tout ce que vous auriez à faire est de convertir un nombre en base 65 en un nombre en base 95 ou en base 94, et vice versa. C'est juste que cela serait un peu lent, et comme indiqué dans une autre réponse, vous ne gagneriez pas beaucoup d'espace.

Voici (non testé) les éléments de base :

def ttoi(texte, base, valeurs_lettres):
    """convertit une chaîne de base-"base" en int"""
    n = 0
    for c in texte:
        n = n * base + valeurs_lettres[c]
    return n

def itot(nombre, base, alphabet, taille_remplissage):
    """convertit un int en une chaîne de base-"base"
       Le résultat est rembourré à gauche jusqu'à "taille_remplissage" en utilisant le caractère de valeur zéro"""
    temp = []
    assert nombre >= 0
    while nombre:
        nombre, digit = divmod(nombre, base)
        temp.append(alphabet[digit])
    return max(0, taille_remplissage - len(temp)) * alphabet[0] + "".join(reversed(temp))

Définitions par exemple pour votre code existant en base 65 :

valeurs_lettres_b65 = {
    'A': 0, 'Z': 25, 'a': 26, 'z': 51, '0': 52, '9': 61,
    # etc
    }
alphabet_b65 = "ABCetcXYZabcetcxyz0123456789.:-"
taille_remplissage_b65 = 19

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X