segunda-feira, 24 de outubro de 2016

Quem faz também desfaz...

Vamos fazer o exercício inverso da encriptação: dado um texto encriptado de acordo com um dado método refazer o texto original. Vamos fazer o exercício para cada um dos três métodos de que falámos.

Separação Pares - Ímpares

Este parece ser um caso trivial. Divididos o texto ao meio e depois tiramos alternadamente os caracteres de cada uma das componentes.
01.def desencripta_1(texto):
02.    # divide ao meio e separa
03.    meio = len(texto)//2
04.    pares = texto[:meio]
05.    impares = texto[meio:]
06.    # constrói texto
07.    novo_texto = ''
08.    for i in range(meio):
09.        novo_texto = novo_texto + pares[i] + impares[i]
10.    return novo_texto
Acontece que se testarmos com vários exemplos verificamos que nalguns casos o resultado não é o esperado. Não precisamos de reflectir muito para verificar que o problema acontece quando o texto tem um número ímpar da caracteres. Neste caso, o número de elementos na posição par é superior em uma unidade do número de elementos nas posições ímpares. Temos pois que ter cuidado quando fazemos a divisão ao meio, diferente em cada um dos casos. Resolvida esta questão uma solução será:
01.def desencripta_12(texto):
02.    # divide ao meio e separa
03.    comp = len(texto)
04.    meio, imp = divmod(comp,2)
05.    pares = texto[:meio]
06.    impares = texto[meio+imp:]
07.    # constrói texto
08.    novo_texto = ''
09.    for i in range(meio):
10.        novo_texto = novo_texto + pares[i] + impares[i]
11.    if imp:
12.        novo_texto = novo_texto + texto[meio]
13.    return novo_texto
Como se pode ver usamos a operação divido que nos permite obter as duas componentes através do mecanismo de desempacotamento:
1.meio,imp = divmod(com,2)
O nome imp estará associado ao objecto 1 (se texto tiver comprimento ímpar) ou ao objecto 0 (caso tenha comprimento par).

Distância Fixa

Neste método, se um caractere é deslocado n posições para a frente na codificação, então na descodificação cada caractere deve ser deslocado n posições para … trás!
1.def desencripta_2(texto_encriptado,chave):
2.    alfabeto = 'abcdefghijklmnopqrstuvwxyz '
3.    texto_normal = ''
4.    for car in texto_encriptado:
5.        indice = alfabeto.find(car)
6.        texto_normal = texto_normal + alfabeto[(indice - chave)%len(alfabeto)]
7.    return texto_normal
Assumimos um alfabeto co mas 26 letras minúsculas mais o espaço em branco, mas a solução pode ser adaptada a qualquer alfabeto sem problemas.

Chave Aleatória

Este caso aparenta ser o mais complexo. Vejamos se é verdade. Comecemos por mostrar o código que permite definir uma chave e encriptar um texto:
01.def encripta_3(texto, alfabeto,chave):
02.    #chave = define_chave(alfabeto)
03.    novo_texto = ''
04.    for car in texto:
05.        ind = alfabeto.index(car)
06.        novo_texto = novo_texto + chave[ind]   
07.    return novo_texto
08. 
09.import random
10. 
11.def define_chave(alfabeto):
12.    simbolos = alfabeto
13.    chave = ''
14.    for car in alfabeto:
15.        novo_simb = random.choice(simbolos)
16.        ind = simbolos.index(novo_simb)
17.        simbolos = simbolos[:ind] + simbolos[ind+1:]
18.        chave = chave + novo_simb   
19.    return chave
Como a correspondência é um para um, se, por exemplo, a “b” no texto original corresponde “h” na chave então quando encontramos no texto codificado um “h” devemos ter um “b” no texto original. Afinal a solução não é assim tão complexa:
1.def desencripta_3(texto_encriptado,alfabeto,chave):
2.    texto_normal = ''
3.    for car in texto_encriptado:
4.        indice = chave.find(car)
5.        texto_normal = texto_normal + alfabeto[indice]
6.    return texto_normal
Mas se pensarmos um pouco mais no que dissemos sobre a correspondência um a um, chegamos à conclusão que codificar e descodificar são o mesmo processo pelo que apenas precisamos de um programa. Dito de outro modo:
1.def desencripta_31(texto,alfabeto,chave):
2.    return encripta_3(texto,chave,alfabeto)
E pronto. Divirta-se a escrever variantes das soluções propostas. Por exemplo, usando sempre o alfabeto como parâmetro.

Sem comentários:

Enviar um comentário