Kod Hamminga (7,4) sięga 1950 roku. Wtedy Richard Hamming pracował jako matematyk w Bell Labs. W każdy piątek Hamming ustawiał maszyny liczące do wykonywania serii obliczeń i zbierał wyniki w następny poniedziałek. Za pomocą kontroli parzystości maszyny te były w stanie wykryć błędy podczas obliczeń. Sfrustrowany, ponieważ zbyt często otrzymywał komunikaty o błędach, Hamming postanowił poprawić wykrywanie błędów i odkrył słynne kody Hamminga.
Mechanika Hamminga (7,4)
Celem kodów Hamminga jest utworzenie zestawu bitów parzystości, które nakładają się na siebie, tak że błąd jednego bitu (jeden bit jest odwracany) w bicie danych lub bit parzystości może zostać wykryty i skorygowany. Tylko w przypadku wystąpienia wielu błędów kod Hamminga nie może odzyskać oryginalnych danych. Może w ogóle nie zauważyć błędu, a nawet poprawić go fałszywie. Dlatego w tym wyzwaniu zajmiemy się tylko błędami jednobitowymi.
Jako przykład kodów Hamminga przyjrzymy się kodowi Hamminga (7,4). Oprócz 4 bitów danych d1, d2, d3, d4
wykorzystuje 3 bity parzystości p1, p2, p3
, które są obliczane przy użyciu następujących równań:
p1 = (d1 + d2 + d4) % 2
p2 = (d1 + d3 + d4) % 2
p3 = (d2 + d3 + d4) % 2
Wynikowe słowo kodowe (dane + bity parzystości) ma postać p1 p2 d1 p3 d2 d3 d4
.
Wykrywanie błędu działa w następujący sposób. Ponownie oblicz bity parzystości i sprawdź, czy pasują one do odebranych bitów parzystości. W poniższej tabeli widać, że każda odmiana błędu jednobitowego daje inne dopasowanie bitów parzystości. Dlatego każdy błąd jednobitowy można zlokalizować i poprawić.
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
Przykład
Niech twoje dane będą 1011
. Bity kontroli parzystości są p1 = 1 + 0 + 1 = 0
, p2 = 1 + 1 + 1 = 1
i p3 = 0 + 1 + 1 = 0
. Połącz dane i bity parzystości, a otrzymasz słowo kodowe 0110011
.
data bits | 1 011
parity bits | 01 0
--------------------
codeword | 0110011
Powiedzmy, że podczas transmisji lub obliczeń szósty bit (= trzeci bit danych) odwraca się. Otrzymujesz słowo 0110001
. Domniemane otrzymane dane to 1001
. Ponownie obliczyć bity parzystości p1 = 1 + 0 + 1 = 0
, p2 = 1 + 0 + 1 = 0
, p3 = 0 + 0 + 1 = 1
. p1
Dopasowuje tylko bity parzystości słowa kodowego 0110001
. Dlatego wystąpił błąd. Patrząc na powyższą tabelę, mówi nam, że wystąpił błąd d3
i możesz odzyskać oryginalne dane 1011
.
Wyzwanie:
Napisz funkcję lub program, który odbiera słowo (7 bitów), jeden z bitów może być nieprawidłowy i odzyskuje oryginalne dane. Format wejściowy (przez STDIN, argument wiersza poleceń, monit lub argument funkcji) może być ciągiem "0110001"
, listą, tablicą [0, 1, 1, 0, 0, 0, 1]
lub liczbą całkowitą w MSB 0b0110001 = 49
. Jak opisano powyżej, kolejność wprowadzania jest następująca p1 p2 d1 p3 d2 d3 d4
. Dane wyjściowe (poprzez wartość zwracaną lub STDOUT) muszą mieć ten sam format, ale w kolejności d1 d2 d3 d4
. Zwracaj / wysyłaj tylko 4 bity danych.
To jest golf golfowy. Dlatego wygrywa najkrótszy kod.
Przypadki testowe:
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]
pod uwagę podstawę drugą, to podaje pozycję niepoprawnego bitu w słowie. (Na podstawie tabeli w pytaniu.) Prawdopodobnie będzie to przydatne w przypadku niektórych algorytmów.Odpowiedzi:
Oktawa,
706655 bajtówTa funkcja
F
konfiguruje macierz dekodowaniaH
, znajduje błąd i koryguje pozycję błędu (jeśli taki istnieje). Następnie zwraca odpowiednie bity danych. Dane wejściowe to standardowy wektor wiersza.@Jakube zasugerował, że powinienem używać Octave zamiast Matlaba, w którym można używać indeksów wyrażeń, co sprawia, że całość znów jest krótsza o 11 bajtów:
Poniżej znajduje się najkrótsze rozwiązanie w Matlabie , ponieważ nie można bezpośrednio używać indeksowania wyrażeń. (Działa to również w Octave.) Był w stanie zastąpić dodatek / mod2
xor
:Stary:
źródło
http://octave-online.net/
tam, gdzie to działa. Może zmienić język?Pie 50x11 = 550
rozmiar kodu to 15. Nie martwi się zbytnio rozmiarem, ale przeszedł wszystkie testy.
źródło
Python, 79
Weź dane wejściowe i wyjściowe jako liczby z najmniej znaczącym bitem po prawej stronie.
Zamiast próbować odzyskać błędy, po prostu próbujemy zakodować każdą możliwą wiadomość
n
od 0 do 15, aż otrzymamy kodowanie, które jest nieco oddalone od tego, co podano. Rekurencja rośnie,n
dopóki nie znajdzie takiej, która działa i zwróci ją. Chociaż nie ma wyraźnego zakończenia, musi kończyć się w ciągu 16 pętli.Wyrażenie
(n&8)*14^(n&4)*19^(n&2)*21^n%2*105
implementuje macierz Hamminga bitowo.Aby sprawdzić pojedynczy błąd, xor lub daną wiadomość obliczamy na jeden, aby uzyskać
e
, i sprawdzamy, czy jest to potęga dwóch (lub 0) klasycznej sztuczki bitoweje&~-e==0
. Ale tak naprawdę nie możemy przypisać zmienneje
do lambda i odwołujemy się do niej dwukrotnie w tym wyrażeniu, więc robimy włamanie do przekazania jej jako opcjonalnego argumentu do następnego rekurencyjnego kroku.źródło
JavaScript (ES6),
928781Funkcja pobierania i zwracania liczby całkowitej w MSB.
Implementacja jest prosta po komentarzu @randomra:
Przetestuj w konsoli Frefox / FireBug
Wynik
źródło
Python 2, 71
Kilka znaków to niedrukowalne znaki ASCII, więc oto wersja zmiany znaczenia:
Wejścia i wyjścia do funkcji są wykonywane jako liczby całkowite.
Korzystam z faktu, że liczba prawidłowych wiadomości wynosi tylko 16, i wszystkie je koduję. Potem próbuję przerzucać różne bity, dopóki nie dostanę jednego z nich.
źródło
Haskell, 152 bajty
Zastosowanie:
a (1,1,1,1,0,1,1)
które wyjścia(1,1,1,1)
Proste rozwiązanie: jeśli
p<x>
nie pasuje, ustaw bit<x>
w liczbie. Jeśli liczba ta jest3
,5
,6
lub7
, flip odpowiednid<y>
.źródło
hamming.hs
i załadować go do ghci Haskell REPL:ghci hamming.hs
. Wywołaj funkcję wa
sposób opisany powyżej. Jedyny znany mi internetowy interpreter haskell ( tryhaskell.org ) wymaga nieco więcej kodu:let a(p,q, ... 2-y in a (1,1,1,1,0,1,1)
Kod maszynowy IA-32, 36 bajtów
Hexdump:
Równoważny kod C:
Procesor x86 automatycznie oblicza parzystość każdego wyniku pośredniego. Posiada dedykowaną instrukcję,
jp
która skacze lub nie, w zależności od parzystości.Nie zostało to wyraźnie określone w wyzwaniu, ale wygodną właściwością kodów hamujących jest to, że można interpretować bity parzystości jako liczbę binarną, a ta liczba wskazuje, który bit został zepsuty podczas transmisji. W rzeczywistości liczba ta jest oparta na 1, przy czym 0 oznacza brak błędów transmisji. Jest to realizowane przez przesunięcie 1 w lewo,
err_pos
a następnie w prawo o1
.Po naprawieniu błędu transmisji kod porządkuje bity danych w wymaganej kolejności. Kod jest zoptymalizowany pod kątem rozmiaru i na początku może być niejasne, jak to działa. Aby to wyjaśnić, to oznaczmy przez
a
,b
,c
,d
bitów danych, a przezP
,Q
iR
bitów parzystości. Następnie:Źródło zestawu (
fastcall
konwencja, z wejściemecx
i wyjściemeax
):źródło