LZ77 (python)

De GirinoWiki

#!/usr/bin/python
# coding: utf-8
 
import sys
 
class lz77:
    """
       Esta classe comprime uma sequencia de caracteres usando
       o algorítmo LZ77 como descrito em
       http://pt.wikipedia.org/wiki/LZ77
 
       Esta é uma implementação didática, para exemplificar
       o funcionamento do algoritmo, e não possui nenhum tipo de
       otimização, por isso seu desempenho em situações reais 
       deve ser muito abaixo do esperado.
    """
    def __init__(self, window_size = 65535, buffer_size=255):
        """
           Carrega os parametros de tamanho de janela e buffer 
           de look-ahead
        """
        self.window_size = window_size
        self.buffer_size = buffer_size
    def encode(self, str):
        """
            Aplica o algoritmo LZ77 na cadeia de entrada, gerando
            uma lista de "tuplas" na saída. Cada tupla correpsonde
            a (posição, tamanho, literal) onde posição é a posição
            relativa da cadeia encontrada na janela, tamanho é o 
            tamanho dessa cadeia e literal é o símbolo que segue
            a cadeia nessa sequencia.
        """
        ret = []
        i = 0
        while i < len(str):
            begin_window = i-self.window_size
            if begin_window < 0:
                begin_window = 0
            window = str[begin_window:i]
            buffer = str[i:i+self.buffer_size]
            tuple = (0, 0, str[i])
            # Este "loop" é o "coração" do algoritmo. Aqui procuramos
            # a maior sequencia dentro da janela (window) que case
            # com o início do buffer. A implementação atual simplesmente
            # procura por ocorrências de substrings cada vez menores
            # do buffer até encontrar alguma. Implementações mais
            # eficientes usariam um dicionário de prefixos, uma trie
            # ou uma tabela de espalhamento.
            for size in range(len(buffer), 0, -1):
                index = window.rfind(buffer[0:size])
                if index >= 0:
                    literal = '' # a string vazia representa 
                                 # o final do arquivo.
                    if i + size < len(str):
                        literal = str[i+size]
                    tuple = (len(window)-index-1, size, literal)
                    break
            i = i + tuple[1] + 1
            ret = ret + [tuple]
        return ret
    def decode(self, list):
        # a decodificação é extremamente simples: basta copiar a
        # subsequÊncia indicada pela tupla para o final da sequencia
        # de saída e acrescentar o novo caractere literal.
        ret = ''
        for tuple in list:
            pos = len(ret) - tuple[0] - 1
            ret = ret + ret[pos:pos+tuple[1]] + tuple[2]
        return ret
 
if __name__ == "__main__":
    str = 'A_ASA_DA_CASA'
    encoder = lz77(8,4)
    encoded = encoder.encode(str)
    print encoded
 
    decoder = lz77(8,4)
    decoded = decoder.decode(encoded)
    print decoded
Ferramentas pessoais
Social Blogging
  • StumbleUpon
  • Adicionar aos Favoritos BlogBlogs
  • Adicionar esta página no Linkk
  • Add to Technorati Favorites
patrocinadores
Espaço comercial