O código de Hamming (7,4) remonta a 1950. Na época, Richard Hamming trabalhava como matemático no Bell Labs. Toda sexta-feira, Hamming preparava as máquinas de calcular para realizar uma série de cálculos e coletava os resultados na segunda-feira seguinte. Usando verificações de paridade, essas máquinas foram capazes de detectar erros durante o cálculo. Frustrado, porque ele recebia mensagens de erro com muita frequência, Hamming decidiu melhorar a detecção de erros e descobriu os famosos códigos de Hamming.
Mecânica do Hamming (7,4)
O objetivo dos códigos Hamming é criar um conjunto de bits de paridade que se sobreponham, de modo que um erro de bit único (um bit seja invertido) em um bit de dados ou um bit de paridade possa ser detectado e corrigido. Somente se ocorrerem vários erros, o código Hamming falhará na recuperação dos dados originais. Pode não notar um erro, ou mesmo corrigi-lo falsamente. Portanto, neste desafio, lidaremos apenas com erros de bit único.
Como um exemplo dos códigos de Hamming, veremos o código de Hamming (7,4). Além de 4 bits de dados, d1, d2, d3, d4
ele usa 3 bits de paridade p1, p2, p3
, calculados usando as seguintes equações:
p1 = (d1 + d2 + d4) % 2
p2 = (d1 + d3 + d4) % 2
p3 = (d2 + d3 + d4) % 2
A palavra de código resultante (dados + bits de paridade) é da forma p1 p2 d1 p3 d2 d3 d4
.
A detecção de um erro funciona da seguinte maneira. Você recalcula os bits de paridade e verifica se eles correspondem aos bits de paridade recebidos. Na tabela a seguir, você pode ver que toda variedade de erro de um bit gera uma correspondência diferente dos bits de paridade. Portanto, todo erro de bit único pode ser localizado e corrigido.
error in bit | p1 | p2 | d1 | p3 | d2 | d3 | d4 | no error
-------------|---------------------------------------------
p1 matches | no | yes| no | yes| no | yes| no | yes
p2 matches | yes| no | no | yes| yes| no | no | yes
p3 matches | yes| yes| yes| no | no | no | no | yes
Exemplo
Deixe seus dados estarem 1011
. Os bits de paridade são p1 = 1 + 0 + 1 = 0
, p2 = 1 + 1 + 1 = 1
e p3 = 0 + 1 + 1 = 0
. Combine os dados e os bits de paridade e você obterá a palavra de código 0110011
.
data bits | 1 011
parity bits | 01 0
--------------------
codeword | 0110011
Digamos que durante uma transmissão ou um cálculo o sexto bit (= terceiro bit de dados) vire. Você recebe a palavra 0110001
. Os supostos dados recebidos são 1001
. Você calcula os bits de paridade de novo p1 = 1 + 0 + 1 = 0
, p2 = 1 + 0 + 1 = 0
, p3 = 0 + 0 + 1 = 1
. p1
Corresponde apenas aos bits de paridade da palavra de código 0110001
. Portanto, ocorreu um erro. Observando a tabela acima, informamos que ocorreu o erro d3
e você pode recuperar os dados originais 1011
.
Desafio:
Escreva uma função ou programa que receba uma palavra (7 bits), um dos bits pode estar errado e recupere os dados originais. O formato de entrada (via STDIN, argumento de linha de comando, argumento de prompt ou função) pode ser uma sequência de caracteres "0110001"
, uma lista ou uma matriz [0, 1, 1, 0, 0, 0, 1]
ou um número inteiro no MSB 0b0110001 = 49
. Como descrito acima, a ordem da entrada é p1 p2 d1 p3 d2 d3 d4
. A saída (via valor de retorno ou STDOUT) deve ser do mesmo formato, mas na ordem d1 d2 d3 d4
. Somente retorne / produza os 4 bits de dados.
Isso é código-golfe. Portanto, o código mais curto vence.
Casos de teste:
1110000 -> 1000 # no error
1100000 -> 1000 # error at 1st data bit
1111011 -> 1111 # error at 2nd data bit
0110001 -> 1011 # error at 3rd data bit (example)
1011011 -> 1010 # error at 4th data bit
0101001 -> 0001 # error at 1st parity bit
1010000 -> 1000 # error at 2nd parity bit
0100010 -> 0010 # error at 3rd parity bit
[is_p3_wrong][is_p2_wrong][is_p1_wrong]
base dois, indica a posição do bit incorreto na palavra. (Com base na tabela da pergunta.) Isso provavelmente será útil para alguns algoritmos.