# # Sam Hadow - Huffman-py # Copyright (C) 2023 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # import re def huffman_decode(encodedData, noeud_actuel): racine = noeud_actuel decodedOutput = [] # cas particulier, si on a qu'un seul sommet dans l'arbre (lettre unique dans le texte d'origine) if (not racine.left and not racine.right): string = ''.join([racine.lettres for _ in encodedData]) return string # cas normal for x in encodedData: if x == '1': noeud_actuel = noeud_actuel.right elif x == '0': noeud_actuel = noeud_actuel.left # On regarde si on est encore dans les noeuds internes, sinon (pour une feuille) on peut décoder une lettre. try: # noeud interne if noeud_actuel.left.lettres == None and noeud_actuel.right.lettres == None: pass except AttributeError: # feuille decodedOutput.append(noeud_actuel.lettres) noeud_actuel = racine if noeud_actuel != racine and (noeud_actuel.right !=None or noeud_actuel.left != None): # si on finit dans un noeud interne c'est que l'arbre ne correspondait pas au texte encodé. raise ValueError ("L'arbre ne correspond pas en texte encodé.") string = ''.join([str(item) for item in decodedOutput]) return string def decode_from_dico(encodedData, dico): # on suppose le dico en entrée de la forme {lettre:binaire} (le même que celui affiché dans la console par l'encodage) # on inverse d'abord les paires key:value (les lettres seront uniques comme les codes) dico = {value:key for key,value in dico.items()} texte = str(encodedData) # on regarde si on a bien un texte en binaire en entrée char_invalide = re.compile('[^01]') if char_invalide.search(texte): raise TypeError ('Le texte en entrée doit être en binaire.') decoded = '' sorted_dict = dict(sorted(dico.items(), key=lambda x: len(x[0]), reverse=False)) while len(texte) > 0: for i,binaire in enumerate(sorted_dict.keys()): if binaire == texte[0:len(binaire)]: # on décode si on trouve la portion du texte codé dans nos codes decoded += sorted_dict[binaire] # on supprime la partie qui vient d'être décodée texte = texte[len(binaire):] # on passe à l'itération suivante du while break # si aucun code correspond après avoir parcouru le dictionnaire on lève une exception elif i == len(sorted_dict.keys())-1: raise ValueError ('Impossible de convertir le texte avec le dictionnaire fourni.') return decoded