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.Respostas:
Oitava,
706655 bytesEsta função
F
está configurando a matriz de decodificaçãoH
, localizando o erro e corrigindo a posição do erro (se houver). Em seguida, ele retorna os bits de dados corretos. Entrada é um vetor de linha padrão.@Jakube sugeriu que eu deveria usar o Octave em vez do Matlab, onde você pode usar índices em expressões, o que torna a coisa toda novamente mais curta: 11 bytes:
A seguir, é a solução mais curta no Matlab , pois você não pode usar diretamente a indexação em expressões. (Isso funciona no Octave também, é claro.) Foi capaz de substituir a adição / mod2 por
xor
:Velho:
fonte
http://octave-online.net/
, onde funciona. Talvez mude o idioma?Piet 50x11 = 550
o tamanho do codel é 15. Não está muito preocupado com o tamanho, mas passou em todos os testes.
fonte
Python, 79
Tome entrada e saída como números com o bit menos significativo à direita.
Em vez de tentar a recuperação de erros, apenas tentamos codificar todas as mensagens possíveis
n
de 0 a 15 até obter uma codificação um pouco distante do que é fornecido. A recursão continua aumentandon
até encontrar uma que funcione e a retorne. Embora não exista terminação explícita, ela deve terminar em 16 loops.A expressão
(n&8)*14^(n&4)*19^(n&2)*21^n%2*105
implementa a matriz de Hamming bit a bit.Para verificar um único erro, xoramos a mensagem fornecida com uma computada para obter
e
e verificamos se é uma potência de dois (ou 0) com o truque de bits clássicoe&~-e==0
. Mas, na verdade, não podemos atribuir à variávele
dentro de um lambda, e nos referimos a ela duas vezes nesta expressão; portanto, tentamos transmiti-la como um argumento opcional para a próxima etapa recursiva.fonte
JavaScript (ES6),
928781Função obtendo e retornando um número inteiro no MSB.
A implementação é direta após o comentário do @randomra:
Teste no console do Frefox / FireBug
Resultado
fonte
Python 2, 71
Vários caracteres são ASCII não imprimíveis, então aqui está uma versão de escape:
A entrada e saída da função são feitas como números inteiros.
Estou aproveitando o fato de que o número de mensagens válidas é de apenas 16 e codificando todas elas. Então tento inverter diferentes bits até obter um desses.
fonte
Haskell, 152 bytes
Uso:
a (1,1,1,1,0,1,1)
quais saídas(1,1,1,1)
Solução simples: se
p<x>
não corresponder, defina o bit<x>
em um número. Se este número é3
,5
,6
ou7
, virar o correspondented<y>
.fonte
hamming.hs
e carregá-lo no ghci Haskell REPL:ghci hamming.hs
. Chame a funçãoa
como descrito acima. O Haskell apenas online intérprete eu sei de ( tryhaskell.org ) requer um pouco mais de código:let a(p,q, ... 2-y in a (1,1,1,1,0,1,1)
Código de máquina IA-32, 36 bytes
Hexdump:
Código C equivalente:
A CPU x86 calcula automaticamente a paridade de cada resultado intermediário. Tem uma instrução dedicada
jp
que salta ou não, dependendo da paridade.Não foi especificado explicitamente no desafio, mas a propriedade conveniente dos códigos hamming é que você pode interpretar os bits de paridade como um número binário, e esse número indica qual bit foi estragado durante a transmissão. Na verdade, esse número é baseado em 1, com 0 significando que não houve erros de transmissão. Isso é implementado deslocando 1 para a esquerda
err_pos
e depois para a direita1
.Após corrigir o erro de transmissão, o código organiza os bits de dados na ordem necessária. O código é otimizado para o tamanho e pode não estar claro a princípio como ele funciona. Para explicar isso, eu por denotar
a
,b
,c
,d
os bits de dados, e porP
,Q
eR
os bits de paridade. Então:Origem da montagem (
fastcall
convenção, com entradaecx
e saídaeax
):fonte