Der Hamming-Code (7,4) stammt aus dem Jahr 1950. Damals arbeitete Richard Hamming als Mathematiker bei Bell Labs. Jeden Freitag stellte Hamming die Rechenmaschinen auf eine Reihe von Berechnungen ein und sammelte die Ergebnisse am folgenden Montag. Mithilfe von Paritätsprüfungen konnten diese Computer Fehler während der Berechnung erkennen. Frustriert, weil er viel zu oft Fehlermeldungen erhielt, beschloss Hamming, die Fehlererkennung zu verbessern, und entdeckte die berühmten Hamming-Codes.
Mechanik der Hamming (7,4)
Das Ziel von Hamming-Codes besteht darin, einen Satz von Paritätsbits zu erzeugen, die sich so überlappen, dass ein Einzelbitfehler (ein Bit wird umgedreht) in einem Datenbit oder einem Paritätsbit erkannt und korrigiert werden kann. Nur wenn mehrere Fehler auftreten, kann der Hamming-Code die ursprünglichen Daten nicht wiederherstellen. Möglicherweise wird ein Fehler überhaupt nicht bemerkt oder sogar falsch korrigiert. Daher werden wir uns in dieser Herausforderung nur mit Einzelbitfehlern befassen.
Als Beispiel für die Hamming-Codes betrachten wir den Hamming-Code (7,4). Zusätzlich zu 4 Datenbits d1, d2, d3, d4
werden 3 Paritätsbits verwendet p1, p2, p3
, die mit den folgenden Gleichungen berechnet werden:
p1 = (d1 + d2 + d4) % 2
p2 = (d1 + d3 + d4) % 2
p3 = (d2 + d3 + d4) % 2
Das resultierende Codewort (Daten + Paritätsbits) hat die Form p1 p2 d1 p3 d2 d3 d4
.
Das Erkennen eines Fehlers funktioniert folgendermaßen. Sie berechnen die Paritätsbits neu und prüfen, ob sie mit den empfangenen Paritätsbits übereinstimmen. In der folgenden Tabelle können Sie sehen, dass jede Sorte eines Einzelbitfehlers eine andere Übereinstimmung der Paritätsbits ergibt. Daher kann jeder Einzelbitfehler lokalisiert und korrigiert werden.
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
Beispiel
Lassen Sie Ihre Daten sein 1011
. Die Paritätsbits sind p1 = 1 + 0 + 1 = 0
, p2 = 1 + 1 + 1 = 1
und p3 = 0 + 1 + 1 = 0
. Kombinieren Sie die Daten und die Paritätsbits und Sie erhalten das Codewort 0110011
.
data bits | 1 011
parity bits | 01 0
--------------------
codeword | 0110011
Sagen wir, während einer Übertragung oder einer Berechnung wird das 6. Bit (= 3. Datenbit) umgeschaltet. Du erhältst das Wort 0110001
. Die angeblich erhaltenen Daten sind 1001
. Sie berechnen die Parity - Bits wieder p1 = 1 + 0 + 1 = 0
, p2 = 1 + 0 + 1 = 0
, p3 = 0 + 0 + 1 = 1
. p1
Stimmt nur mit den Paritätsbits des Codeworts überein 0110001
. Daher ist ein Fehler aufgetreten. In der obigen Tabelle sehen Sie, dass der Fehler in aufgetreten ist d3
und Sie die ursprünglichen Daten wiederherstellen können 1011
.
Herausforderung:
Schreiben Sie eine Funktion oder ein Programm, das ein Wort (7 Bits) empfängt, eines der Bits ist möglicherweise falsch, und stellen Sie die ursprünglichen Daten wieder her. Das Eingabeformat (über STDIN, Befehlszeilenargument, Eingabeaufforderung oder Funktionsargument) kann eine Zeichenfolge "0110001"
, eine Liste oder ein Array [0, 1, 1, 0, 0, 0, 1]
oder eine Ganzzahl in MSB sein 0b0110001 = 49
. Wie oben beschrieben ist die Reihenfolge der Eingabe p1 p2 d1 p3 d2 d3 d4
. Die Ausgabe (über Rückgabewert oder STDOUT) muss dasselbe Format haben, jedoch in der Reihenfolge d1 d2 d3 d4
. Nur die 4 Datenbits zurückgeben / ausgeben.
Das ist Code-Golf. Daher gewinnt der kürzeste Code.
Testfälle:
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]
Basis zwei verwenden, wird die Position des falschen Bits im Wort angegeben. (Basierend auf der Tabelle in der Frage.) Dies wird wahrscheinlich für einige Algorithmen nützlich sein.Antworten:
Oktave,
706655 BytesDiese Funktion
F
richtet die Dekodierungsmatrix einH
, findet den Fehler und korrigiert die Position des Fehlers (falls vorhanden). Dann werden die richtigen Datenbits zurückgegeben. Die Eingabe ist ein Standardzeilenvektor.@Jakube schlug ich Octave statt Matlab verwenden sollten , wo Sie können Indizes auf Ausdrücke verwenden, die das Ganze wieder kürzer 11 Bytes macht:
Das Folgende ist die kürzeste Lösung in Matlab , da Sie die Indizierung für Ausdrücke nicht direkt verwenden können. (Das funktioniert natürlich auch in Octave.) Addition / Mod2 konnte ersetzt werden durch
xor
:Alt:
quelle
http://octave-online.net/
, wo es funktioniert. Vielleicht die Sprache wechseln?Piet 50x11 = 550
Die Codelgröße ist 15. Die Größe ist nicht sonderlich wichtig, aber sie hat alle Tests bestanden.
quelle
Python, 79
Nehmen Sie die Eingabe und Ausgabe als Zahlen mit dem niedrigstwertigen Bit rechts.
Anstatt eine Fehlerbehebung zu versuchen, versuchen wir einfach, jede mögliche Nachricht
n
von 0 bis 15 zu codieren, bis wir eine Codierung erhalten, die ein bisschen von dem entfernt ist, was gegeben ist. Die Rekursion wird so lange inkrementiert,n
bis eine funktionierende gefunden und zurückgegeben wird. Obwohl es keine explizite Kündigung gibt, muss sie innerhalb von 16 Schleifen enden.Der Ausdruck
(n&8)*14^(n&4)*19^(n&2)*21^n%2*105
implementiert die Hamming-Matrix bitweise.Um nach einem einzelnen Fehler zu suchen, wird die angegebene Nachricht mit einem berechneten Fehler ermittelt
e
und mit dem klassischen Bit-Trick überprüft, ob es sich um eine Zweierpotenz (oder 0) handelte&~-e==0
. Wir können der Variablene
in einem Lambda jedoch nicht wirklich etwas zuweisen , und wir verweisen in diesem Ausdruck zweimal darauf, sodass wir sie als optionales Argument an den nächsten rekursiven Schritt übergeben.quelle
JavaScript (ES6),
928781Funktion zum Abrufen und Zurückgeben einer Ganzzahl in MSB.
Die Implementierung ist direkt nach @randomra Kommentar:
Test In der Frefox / FireBug-Konsole
Ausgabe
quelle
Python 2, 71
Einige Zeichen sind nicht druckbares ASCII, daher ist hier eine maskierte Version:
Die Ein- und Ausgabe der Funktion erfolgt als Ganzzahl.
Ich nutze die Tatsache, dass die Anzahl der gültigen Nachrichten nur 16 beträgt, und codiere sie alle hart. Dann versuche ich, verschiedene Teile umzudrehen, bis ich eine davon bekomme.
quelle
Haskell, 152 Bytes
Verwendung:
a (1,1,1,1,0,1,1)
welche Ausgänge(1,1,1,1)
Einfache Lösung: Wenn
p<x>
nicht, Bit<x>
in einer Zahl setzen. Wenn diese Zahl ist3
,5
,6
oder7
, Flip das entsprechended<y>
.quelle
hamming.hs
und in den GHCI Haskell REPL laden:ghci hamming.hs
. Rufen Sie die Funktiona
wie oben beschrieben auf. Der einzige mir bekannte Online-Haskell-Interpreter ( tryhaskell.org ) benötigt etwas mehr Code:let a(p,q, ... 2-y in a (1,1,1,1,0,1,1)
IA-32 Maschinencode, 36 Bytes
Hexdump:
Äquivalenter C-Code:
Die x86-CPU berechnet automatisch die Parität jedes Zwischenergebnisses. Es gibt eine spezielle Anweisung
jp
, die abhängig von der Parität springt oder nicht springt.Es wurde in der Abfrage nicht explizit angegeben, aber die praktische Eigenschaft von Hamming-Codes besteht darin, dass Sie die Paritätsbits als Binärzahl interpretieren können. Diese Zahl gibt an, welches Bit während der Übertragung fehlerhaft war. Tatsächlich basiert diese Zahl auf 1, wobei 0 bedeutet, dass keine Übertragungsfehler aufgetreten sind. Dies wird durch Verschieben von 1 nach links
err_pos
und dann nach rechts umgesetzt1
.Nach dem Beheben des Übertragungsfehlers ordnet der Code die Datenbits in der erforderlichen Reihenfolge an. Der Code ist für die Größe optimiert und es kann zunächst unklar sein, wie er funktioniert. Um zu erklären, ich bezeichne
a
,b
,c
,d
die Datenbits und durchP
,Q
undR
die Parity - Bits. Dann:Assembly-Quelle (
fastcall
Konvention, mit Eingabe inecx
und Ausgabe ineax
):quelle