El código Hamming (7,4) se remonta a 1950. En aquel entonces, Richard Hamming trabajó como matemático en los Laboratorios Bell. Todos los viernes, Hamming configuró las máquinas de cálculo para realizar una serie de cálculos y recolectó los resultados el lunes siguiente. Mediante el uso de verificaciones de paridad, estas máquinas pudieron detectar errores durante el cálculo. Frustrado, porque recibió mensajes de error con demasiada frecuencia, Hamming decidió mejorar la detección de errores y descubrió los famosos códigos de Hamming.
Mecánica del Hamming (7,4)
El objetivo de los códigos de Hamming es crear un conjunto de bits de paridad que se superpongan de tal manera que se pueda detectar y corregir un error de un solo bit (se invierte un bit) en un bit de datos o un bit de paridad. Solo si se producen varios errores, el código de Hamming no puede recuperar los datos originales. Es posible que no note ningún error, o incluso que lo corrija falsamente. Por lo tanto, en este desafío solo trataremos con errores de un solo bit.
Como ejemplo de los códigos de Hamming, veremos el código de Hamming (7,4). Además de 4 bits de datos d1, d2, d3, d4
, utiliza 3 bits de paridad p1, p2, p3
, que se calculan utilizando las siguientes ecuaciones:
p1 = (d1 + d2 + d4) % 2
p2 = (d1 + d3 + d4) % 2
p3 = (d2 + d3 + d4) % 2
La palabra de código resultante (datos + bits de paridad) tiene la forma p1 p2 d1 p3 d2 d3 d4
.
La detección de un error funciona de la siguiente manera. Vuelve a calcular los bits de paridad y comprueba si coinciden con los bits de paridad recibidos. En la siguiente tabla puede ver que cada variedad de un error de un solo bit produce una coincidencia diferente de los bits de paridad. Por lo tanto, cada error de un solo bit puede ser localizado y corregido.
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
Ejemplo
Deja que tus datos sean 1011
. Los bits de paridad son p1 = 1 + 0 + 1 = 0
, p2 = 1 + 1 + 1 = 1
y p3 = 0 + 1 + 1 = 0
. Combine los datos y los bits de paridad y obtendrá la palabra de código 0110011
.
data bits | 1 011
parity bits | 01 0
--------------------
codeword | 0110011
Digamos que durante una transmisión o un cálculo, el sexto bit (= tercer bit de datos) se voltea. Recibes la palabra 0110001
. Los supuestos datos recibidos son 1001
. Se calculan los bits de paridad de nuevo p1 = 1 + 0 + 1 = 0
, p2 = 1 + 0 + 1 = 0
, p3 = 0 + 0 + 1 = 1
. Solo p1
coincide con los bits de paridad de la palabra de código 0110001
. Por lo tanto, se produjo un error. Mirando la tabla anterior, nos dice que ocurrió el error d3
y puede recuperar los datos originales 1011
.
Desafío:
Escriba una función o un programa que reciba una palabra (7 bits), uno de los bits podría estar equivocado y recupere los datos originales. El formato de entrada (a través de STDIN, argumento de línea de comando, argumento de solicitud o función) puede ser una cadena "0110001"
, una lista o una matriz [0, 1, 1, 0, 0, 0, 1]
o un entero en MSB 0b0110001 = 49
. Como se describió anteriormente, el orden de la entrada es p1 p2 d1 p3 d2 d3 d4
. La salida (a través del valor de retorno o STDOUT) debe ser del mismo formato, pero en el orden d1 d2 d3 d4
. Solo devuelve / emite los 4 bits de datos.
Este es el código de golf. Por lo tanto, el código más corto gana.
Casos de prueba:
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 dos, le da la posición del bit incorrecto en la palabra. (Basado en la tabla de la pregunta). Esto probablemente será útil para algunos algoritmos.Respuestas:
Octava,
706655 bytesEsta función
F
está configurando la matriz de decodificaciónH
, encontrando el error y corrigiendo la posición del error (si existe). Entonces está devolviendo los bits de datos correctos. La entrada es un vector de fila estándar.@Jakube sugirió que debería utilizar Octave en lugar de Matlab donde se puede utilizar índices en las expresiones, lo que hace todo de nuevo más cortos 11 bytes:
La siguiente es la solución más corta en Matlab , ya que no puede usar directamente la indexación en expresiones. (Esto también funciona en Octave, por supuesto). Pude reemplazar la suma / mod2 con
xor
:Antiguo:
fuente
http://octave-online.net/
, donde funciona. Tal vez cambiar el idioma?Piet 50x11 = 550
el tamaño del codel es 15. No le preocupa demasiado el tamaño, pero pasó todas las pruebas.
fuente
Python, 79
Tome la entrada y la salida como números con el bit menos significativo a la derecha.
En lugar de intentar la recuperación de errores, solo intentamos codificar cada mensaje posible
n
de 0 a 15 hasta que obtengamos una codificación que esté un poco lejos de lo que se proporciona. La recursión sigue incrementándosen
hasta que encuentra una que funciona y la devuelve. Aunque no hay una terminación explícita, debe terminar dentro de 16 bucles.La expresión
(n&8)*14^(n&4)*19^(n&2)*21^n%2*105
implementa la matriz de Hamming bit a bit.Para verificar un solo error, revisamos el mensaje dado con uno calculado para obtenerlo
e
, y verificamos si es una potencia de dos (o 0) con el clásico truco de bitse&~-e==0
. Pero, en realidad no podemos asignar a la variablee
dentro de una lambda, y nos referimos a ella dos veces en esta expresión, por lo que hacemos un truco para pasarla como un argumento opcional al siguiente paso recursivo.fuente
JavaScript (ES6),
928781Función de obtener y devolver un número entero en MSB.
La implementación es sencilla siguiendo el comentario de @randomra:
Prueba en la consola de Frefox / FireBug
Salida
fuente
Pitón 2, 71
Varios caracteres son ASCII no imprimibles, así que aquí hay una versión con escape:
La entrada y salida a la función se realizan como enteros.
Aprovecho el hecho de que la cantidad de mensajes válidos es solo 16 y los codifico todos. Luego trato de voltear diferentes bits hasta que obtengo uno de esos.
fuente
Haskell, 152 bytes
Uso:
a (1,1,1,1,0,1,1)
que salidas(1,1,1,1)
Solución directa: si
p<x>
no coincide, establezca el bit<x>
en un número. Si este número es3
,5
,6
o7
, darle la vuelta al correspondiented<y>
.fuente
hamming.hs
, y cargarlo en la ghci Haskell REPL:ghci hamming.hs
. Llame a la funcióna
como se describe anteriormente. El único intérprete de haskell en línea que conozco ( tryhaskell.org ) requiere más 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:
La CPU x86 calcula automáticamente la paridad de cada resultado intermedio. Tiene una instrucción dedicada
jp
que salta o no salta dependiendo de la paridad.No se especificó explícitamente en el desafío, pero la propiedad conveniente de los códigos hamming es que puede interpretar los bits de paridad como un número binario, y este número indica qué bit se echó a perder durante la transmisión. En realidad, este número se basa en 1, con 0, lo que significa que no hubo errores de transmisión. Esto se implementa desplazando 1 hacia la izquierda
err_pos
y luego hacia la derecha1
.Después de corregir el error de transmisión, el código organiza los bits de datos en el orden necesario. El código está optimizado para el tamaño, y al principio puede no estar claro cómo funciona. Para explicarlo, denotamos por
a
,b
,c
,d
los bits de datos, y porP
,Q
yR
los bits de paridad. Luego:Fuente de ensamblaje (
fastcall
convención, con entradaecx
y salidaeax
):fuente