Le code Hamming (7,4) remonte à 1950. À l'époque, Richard Hamming travaillait comme mathématicien aux Bell Labs. Chaque vendredi, Hamming réglait les machines à calculer pour effectuer une série de calculs et collectait les résultats le lundi suivant. Grâce à des contrôles de parité, ces machines ont pu détecter des erreurs lors du calcul. Frustré, parce qu'il recevait trop souvent des messages d'erreur, Hamming a décidé d'améliorer la détection des erreurs et a découvert les fameux codes Hamming.
Mécanique du Hamming (7,4)
Le but des codes de Hamming est de créer un ensemble de bits de parité qui se chevauchent de telle sorte qu'une erreur sur un bit (un bit est inversé) dans un bit de données ou un bit de parité puisse être détectée et corrigée. Ce n'est qu'en cas d'erreurs multiples que le code Hamming ne parvient pas à récupérer les données d'origine. Il peut ne pas remarquer du tout d'erreur, ni même le corriger faussement. Par conséquent, dans ce défi, nous ne traiterons que des erreurs mono-bit.
Comme exemple des codes de Hamming, nous examinerons le code de Hamming (7,4). En plus de 4 bits de données, d1, d2, d3, d4
il utilise 3 bits de parité p1, p2, p3
, qui sont calculés à l'aide des équations suivantes:
p1 = (d1 + d2 + d4) % 2
p2 = (d1 + d3 + d4) % 2
p3 = (d2 + d3 + d4) % 2
Le mot de code résultant (données + bits de parité) est de la forme p1 p2 d1 p3 d2 d3 d4
.
La détection d'une erreur fonctionne de la manière suivante. Vous recalculez les bits de parité et vérifiez s'ils correspondent aux bits de parité reçus. Dans le tableau suivant, vous pouvez voir que chaque variété d'erreur sur un seul bit produit une correspondance différente des bits de parité. Par conséquent, chaque erreur sur un seul bit peut être localisée et corrigée.
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
Exemple
Laissez vos données être 1011
. Les bits de parité sont p1 = 1 + 0 + 1 = 0
, p2 = 1 + 1 + 1 = 1
et p3 = 0 + 1 + 1 = 0
. Combinez les données et les bits de parité et vous obtenez le mot de code 0110011
.
data bits | 1 011
parity bits | 01 0
--------------------
codeword | 0110011
Disons que lors d'une transmission ou d'un calcul le 6ème bit (= 3ème bit de données) bascule. Vous recevez le mot 0110001
. Les prétendues données reçues sont 1001
. On calcule à nouveau les bits de parité p1 = 1 + 0 + 1 = 0
, p2 = 1 + 0 + 1 = 0
, p3 = 0 + 0 + 1 = 1
. Correspond uniquement p1
aux bits de parité du mot de code 0110001
. Une erreur s'est donc produite. En regardant le tableau ci-dessus, nous indique que l'erreur s'est produite dans d3
et vous pouvez récupérer les données d'origine 1011
.
Défi:
Écrivez une fonction ou un programme qui reçoit un mot (7 bits), l'un des bits peut être incorrect et récupérez les données d'origine. Le format d'entrée (via STDIN, argument de ligne de commande, invite ou fonction) peut être une chaîne "0110001"
, une liste ou un tableau [0, 1, 1, 0, 0, 0, 1]
ou un entier dans MSB 0b0110001 = 49
. Comme décrit ci-dessus, l'ordre de l'entrée est p1 p2 d1 p3 d2 d3 d4
. La sortie (via la valeur de retour ou STDOUT) doit être du même format, mais dans l'ordre d1 d2 d3 d4
. Renvoie / émet uniquement les 4 bits de données.
C'est du code-golf. Par conséquent, le code le plus court l'emporte.
Cas de test:
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]
en base deux, cela donne la position du bit incorrect dans le mot. (Basé sur le tableau de la question.) Cela sera probablement utile pour certains algorithmes.Réponses:
Octave,
706655 octetsCette fonction
F
configure la matrice de décodageH
, recherche l'erreur et corrige la position de l'erreur (s'il y en a une). Ensuite, il renvoie les bons bits de données. L'entrée est un vecteur de ligne standard.@Jakube a suggéré que je devrais utiliser Octave au lieu de Matlab où vous pouvez utiliser des index sur les expressions, ce qui raccourcit encore le tout de 11 octets:
Voici la solution la plus courte dans Matlab , car vous ne pouvez pas utiliser directement l'indexation sur les expressions. (Cela fonctionne aussi dans Octave, bien sûr.) A pu remplacer addition / mod2 par
xor
:Vieux:
la source
http://octave-online.net/
, là où cela fonctionne. Peut-être changer la langue?Piet 50x11 = 550
la taille du codel est de 15. Pas trop préoccupé par la taille, mais il a passé tous les tests.
la source
Python, 79
Prenez l'entrée et la sortie sous forme de nombres avec le bit le moins significatif à droite.
Au lieu de tenter une récupération d'erreur, nous essayons simplement de coder tous les messages possibles
n
de 0 à 15 jusqu'à ce que nous obtenions un codage un peu éloigné de ce qui est donné. La récursivité continue à incrémentern
jusqu'à ce qu'elle en trouve une qui fonctionne et la renvoie. Bien qu'il n'y ait pas de terminaison explicite, elle doit se terminer dans 16 boucles.L'expression
(n&8)*14^(n&4)*19^(n&2)*21^n%2*105
implémente la matrice de Hamming au niveau du bit.Pour vérifier une seule erreur, nous xor le message donné avec un calculé pour obtenir
e
, et vérifier si c'est une puissance de deux (ou 0) avec le bit-trick classiquee&~-e==0
. Mais, nous ne pouvons pas réellement assigner à la variablee
dans un lambda, et nous nous référons à elle deux fois dans cette expression, nous faisons donc un hack de la passer comme argument facultatif à la prochaine étape récursive.la source
JavaScript (ES6),
928781Fonction obtenant et renvoyant un entier dans MSB.
L'implémentation est simple suite au commentaire @randomra:
Test dans la console Frefox / FireBug
Production
la source
Python 2, 71
Plusieurs caractères sont ASCII non imprimables alors voici une version échappée:
L'entrée et la sortie de la fonction se font sous forme d'entiers.
Je profite du fait que le nombre de messages valides n'est que de 16 et je les code tous en dur. Ensuite, j'essaie de retourner différents bits jusqu'à ce que j'en reçoive un.
la source
Haskell, 152 octets
Utilisation:
a (1,1,1,1,0,1,1)
quelles sorties(1,1,1,1)
Solution simple: si
p<x>
ne correspond pas, définissez le bit<x>
dans un nombre. Si ce nombre est3
,5
,6
ou7
, retournez le correspondantd<y>
.la source
hamming.hs
et le charger dans le Haskell REPL ghci:ghci hamming.hs
. Appelez la fonctiona
comme décrit ci-dessus. Le seul interprète de haskell en ligne que je connaisse ( tryhaskell.org ) nécessite un peu plus de code:let a(p,q, ... 2-y in a (1,1,1,1,0,1,1)
Code machine IA-32, 36 octets
Hexdump:
Code C équivalent:
Le processeur x86 calcule automatiquement la parité de chaque résultat intermédiaire. Il a une instruction dédiée
jp
qui saute ou non saute selon la parité.Il n'a pas été spécifié explicitement dans le défi, mais la propriété pratique des codes de brouillage est que vous pouvez interpréter les bits de parité comme un nombre binaire, et ce nombre indique quel bit a été gâché pendant la transmission. En fait, ce nombre est basé sur 1, 0 signifiant qu'il n'y a eu aucune erreur de transmission. Ceci est implémenté en décalant 1 de gauche
err_pos
puis de droite1
.Après avoir corrigé l'erreur de transmission, le code organise les bits de données dans l'ordre requis. Le code est optimisé pour la taille, et il peut ne pas être clair au début comment il fonctionne. Pour l' expliquer, je note
a
,b
,c
,d
les bits de données, et parP
,Q
etR
les bits de parité. Alors:Source de l'assembly (
fastcall
convention, avec entréeecx
et sortieeax
):la source