Sửa lỗi bằng cách sử dụng Hamming (7,4)


19

Mã Hamming (7,4) trở lại năm 1950. Trước đó Richard Hamming làm việc như một nhà toán học tại Bell Labs. Mỗi Thứ Sáu Hamming thiết lập các máy tính để thực hiện một loạt tính toán và thu thập kết quả vào thứ Hai sau. Sử dụng kiểm tra chẵn lẻ, các máy này có thể phát hiện lỗi trong quá trình tính toán. Thất vọng, vì nhận được thông báo lỗi quá thường xuyên, Hamming quyết định cải thiện phát hiện lỗi và phát hiện ra các mã Hamming nổi tiếng.

Cơ học của Hamming (7,4)

Mục tiêu của mã Hamming là tạo ra một tập hợp các bit chẵn lẻ trùng nhau sao cho một lỗi một bit (một bit bị lật) trong một bit dữ liệu hoặc một bit chẵn lẻ có thể được phát hiện và sửa chữa. Chỉ khi xảy ra nhiều lỗi, mã Hamming không thể khôi phục dữ liệu gốc. Nó có thể không nhận thấy một lỗi nào cả, hoặc thậm chí sửa nó sai. Do đó, trong thử thách này, chúng tôi sẽ chỉ xử lý các lỗi đơn bit.

Để làm ví dụ về mã Hamming, chúng ta sẽ xem xét mã Hamming (7,4). Ngoài ra với 4 bit dữ liệu, d1, d2, d3, d4nó sử dụng 3 bit chẵn lẻ p1, p2, p3, được tính bằng các phương trình sau:

p1 = (d1 + d2 + d4) % 2
p2 = (d1 + d3 + d4) % 2
p3 = (d2 + d3 + d4) % 2

Từ mã kết quả (dữ liệu + bit chẵn lẻ) có dạng p1 p2 d1 p3 d2 d3 d4.

Phát hiện lỗi hoạt động theo cách sau. Bạn tính toán lại các bit chẵn lẻ và kiểm tra xem chúng có khớp với các bit chẵn lẻ nhận được không. Trong bảng sau đây bạn có thể thấy, mỗi loại lỗi một bit đều mang lại sự khớp khác nhau của các bit chẵn lẻ. Do đó, mọi lỗi đơn bit có thể được bản địa hóa và sửa chữa.

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

Thí dụ

Hãy để dữ liệu của bạn được 1011. Các bit chẵn lẻ là p1 = 1 + 0 + 1 = 0, p2 = 1 + 1 + 1 = 1p3 = 0 + 1 + 1 = 0. Kết hợp dữ liệu và các bit chẵn lẻ và bạn có được từ mã 0110011.

data bits   |   1 011
parity bits | 01 0
--------------------
codeword    | 0110011

Hãy nói trong khi truyền hoặc tính toán bit thứ 6 (= bit dữ liệu thứ 3) lật. Bạn nhận được từ 0110001. Các dữ liệu bị cáo buộc nhận được là 1001. Bạn tính toán các bit chẵn lẻ nữa p1 = 1 + 0 + 1 = 0, p2 = 1 + 0 + 1 = 0, p3 = 0 + 0 + 1 = 1. Chỉ p1khớp với các bit chẵn lẻ của từ mã 0110001. Do đó, một lỗi xảy ra. Nhìn vào bảng trên, cho chúng tôi biết rằng lỗi xảy ra d3và bạn có thể khôi phục dữ liệu gốc 1011.

Thử thách:

Viết một hàm hoặc một chương trình, nhận một từ (7 bit), một trong các bit có thể sai và khôi phục dữ liệu gốc. Định dạng đầu vào (thông qua STDIN, đối số dòng lệnh, đối số dấu nhắc hoặc hàm) có thể là một chuỗi "0110001", một danh sách hoặc một mảng [0, 1, 1, 0, 0, 0, 1]hoặc một số nguyên trong MSB 0b0110001 = 49. Như mô tả ở trên, thứ tự của đầu vào là p1 p2 d1 p3 d2 d3 d4. Đầu ra (thông qua giá trị trả về hoặc STDOUT) phải có cùng định dạng, nhưng theo thứ tự d1 d2 d3 d4. Chỉ trả về / xuất 4 bit dữ liệu.

Đây là mã golf. Do đó mã ngắn nhất sẽ thắng.

Các trường hợp thử nghiệm:

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


1
Có một lý do cụ thể nào cho bit chẵn lẻ cuối cùng được đưa ra sau bit dữ liệu đầu tiên không?
xnor

2
@xnor Về mặt toán học, nó không tạo ra bất kỳ sự khác biệt nào, tại vị trí của các bit chẵn lẻ. Trong lịch sử, họ được đặt trên vị trí quyền lực của hai. Ví dụ, Hamming (15,11) có các bit chẵn lẻ ở các vị trí 1, 2, 4 và 8.
Jakube

4
@xnor Nếu bạn lấy [is_p3_wrong][is_p2_wrong][is_p1_wrong]ở cơ sở hai, nó sẽ đưa ra vị trí của bit không chính xác trong từ. (Dựa trên bảng trong câu hỏi.) Điều này có thể sẽ hữu ích cho một số thuật toán.
Randomra

Rất hay :) Khi bạn viết "Viết hàm hoặc chương trình, nhận một từ (7 bit), một trong số chúng có thể sai, [...]" Tôi nghĩ bạn có nghĩa là một trong số các bit có thể sai nhưng bạn thực sự nói một trong những từ có thể được.

@Lembik Chắc chắn, làm rõ nó.
Jakube

Câu trả lời:


6

Octave, 70 66 55 byte

Hàm Fnày đang thiết lập ma trận giải mã H, tìm lỗi và sửa vị trí lỗi (nếu có). Sau đó, nó đang trả về các bit dữ liệu đúng. Đầu vào là một vector hàng tiêu chuẩn.

@Jakube đề nghị tôi nên sử dụng Octave thay vì Matlab nơi bạn có thể sử dụng các chỉ mục trên biểu thức, điều này làm cho toàn bộ nội dung lại ngắn hơn 11 byte:

F=@(c)xor(c,1:7==bi2de(mod(c*de2bi(1:7,3),2)))([3,5:7])

Sau đây là giải pháp ngắn nhất trong Matlab , vì bạn không thể trực tiếp sử dụng lập chỉ mục trên các biểu thức. (Tất nhiên, điều này cũng hoạt động trong Octave.) Đã có thể thay thế bổ sung / mod2 bằng xor:

f=@(c)c([3,5:7]);F=@(c)f(xor(c,1:7==bi2de(mod(c*de2bi(1:7,3),2))))

Cũ:

f=@(c)c([3,5:7]);F=@(c)f(mod(c+(1:7==bi2de(mod(c*de2bi(1:7,3),2))),2))

Cảm ơn bạn, nhưng điều này không hoạt động, thật không may, bạn chỉ có thể truy cập các biến theo cách đó ...
flawr 16/215

1
Không cài đặt Matlab, tôi chỉ sử dụng http://octave-online.net/, nơi nó hoạt động. Có thể thay đổi ngôn ngữ?
Jakube

Ồ, tôi đã sẵn sàng nghi ngờ rằng quãng tám có thể làm như vậy, nhưng sau đó tôi sẽ thay đổi ngôn ngữ, cảm ơn bạn rất nhiều!
flawr 16/2/2015

14

Thành phố 50x11 = 550

nhập mô tả hình ảnh ở đây

kích thước codel là 15. Không quá quan tâm đến kích thước, nhưng nó đã vượt qua tất cả các bài kiểm tra.


4
Tôi thích điều này với bối cảnh của vấn đề.

1
@Optimizer "kích thước codel" thực chất là hệ số phóng đại của chương trình piet. Tại đây, mỗi pixel logic (hoặc codel) đã được mở rộng thành khối 15x15 để dễ nhìn hơn. Đó là những gì tôi muốn nói, không phải là "kích thước mã"
captncraig

à ..... xấu của tôi
Trình tối ưu hóa

8

Con trăn, 79

f=lambda x,n=0,e=3:e&~-e and f(x,n+1,(n&8)*14^(n&4)*19^(n&2)*21^n%2*105^x)or~-n

Lấy đầu vào và đầu ra dưới dạng số có bit có trọng số thấp nhất ở bên phải.

Thay vì cố gắng phục hồi lỗi, chúng tôi chỉ thử mã hóa mọi tin nhắn có thể ntừ 0 đến 15 cho đến khi chúng tôi nhận được một mã hóa cách xa những gì đã cho. Đệ quy tiếp tục tăng ncho đến khi nó tìm thấy một hoạt động và trả lại nó. Mặc dù không có sự chấm dứt rõ ràng, nó phải kết thúc trong vòng 16 vòng.

Biểu thức (n&8)*14^(n&4)*19^(n&2)*21^n%2*105thực hiện ma trận Hamming theo chiều bit.

Để kiểm tra một lỗi duy nhất, chúng tôi xor thông báo đã cho với một thông báo được tính toán evà kiểm tra xem đó có phải là lũy thừa của hai (hoặc 0) với thủ thuật bit cổ điển hay không e&~-e==0. Nhưng, chúng ta thực sự không thể gán cho biến etrong lambda và chúng ta đề cập đến nó hai lần trong biểu thức này, vì vậy chúng ta thực hiện một bước chuyển nó như một đối số tùy chọn cho bước đệ quy tiếp theo.


7

JavaScript (ES6), 92 87 81

Hàm nhận và trả về một số nguyên trong MSB.
Việc triển khai rất đơn giản sau khi nhận xét @randomra:

  • calc p3wrong | p2wrong | p1wrong (dòng 2,3,4)
  • sử dụng nó như một mặt nạ bit để lật bit không chính xác (dòng 1),
  • sau đó chỉ trả về các bit dữ liệu (dòng cuối cùng)
F=w=>(w^=128>>(
  (w^w*2^w*4^w/2)&4|
  (w/8^w^w*2^w/16)&2|
  (w/16^w/4^w^w/64)&1
))&7|w/2&8

Kiểm tra trong bảng điều khiển Frefox / FireBug

;[0b1110000,0b1100000,0b1111011,0b0110001,
0b1011011,0b0101001,0b1010000,0b0100010]
.map(x=>x.toString(2)+'->'+F(x).toString(2))

Đầu ra

["1110000->1000", "1100000->1000", "1111011->1111", "110001->1011", "1011011->1010", "101001->1", "1010000->1000", "100010->10"]

1
Tôi thực sự thích giải pháp hoạt động bitwise nhỏ gọn của bạn =)
flawr 16/215

4

Con trăn 2, 71

f=lambda i,b=3:i&7|i/2&8if chr(i)in'\0%*3<CLUZfip'else f(i^b/2,b*2)

Một số ký tự không thể in được ASCII, vì vậy đây là phiên bản thoát:

f=lambda i,b=3:i&7|i/2&8if chr(i)in'\0\x0f\x16\x19%*3<CLUZfip\x7f'else f(i^b/2,b*2)

Đầu vào và đầu ra cho hàm được thực hiện dưới dạng số nguyên.

Tôi đang lợi dụng thực tế là số lượng tin nhắn hợp lệ chỉ có 16 và mã hóa tất cả chúng. Sau đó, tôi thử lật các bit khác nhau cho đến khi tôi có được một trong số đó.


3

Haskell, 152 byte

a(p,q,d,r,e,f,g)=b$(d+e)#p+2*(d+f)#q+4*(e+f)#r where b 3=(1-d,e,f,g);b 5=(d,1-e,f,g);b 6=(d,e,1-f,g);b 7=(d,e,f,g-1);b _=(d,e,f,g);x#y=abs$(x+g)`mod`2-y

Cách sử dụng: a (1,1,1,1,0,1,1)đầu ra nào(1,1,1,1)

Giải pháp đơn giản: nếu p<x>không khớp, đặt bit <x>trong một số. Nếu con số này 3, 5, 6hoặc 7, lật tương ứng d<y>.


Bạn có thể thêm một số hướng dẫn về cách gọi mã của mình (ví dụ: sử dụng trình biên dịch trực tuyến như ideone.com ) không? Tôi luôn nhận được một số lỗi kỳ lạ (rất có thể là lỗi của tôi).
Jakube

@Jakube: lưu mã vào một tệp, nói hamming.hsvà tải nó vào Haskell REPL ghci : ghci hamming.hs. Gọi hàm anhư mô tả ở trên. Trình thông dịch haskell trực tuyến duy nhất mà tôi biết ( tryhaskell.org ) yêu cầu thêm một số mã:let a(p,q, ... 2-y in a (1,1,1,1,0,1,1)
nimi

3

Mã máy IA-32, 36 byte

Hexdump:

33 c0 40 91 a8 55 7a 02 d0 e1 a8 66 7a 03 c0 e1
02 a8 78 7a 03 c1 e1 04 d0 e9 32 c1 24 74 04 04
c0 e8 03 c3

Mã C tương đương:

unsigned parity(unsigned x)
{
    if (x == 0)
        return 0;
    else
        return x & 1 ^ parity(x >> 1);
}

unsigned fix(unsigned x)
{
    unsigned e1, e2, e3, err_pos, data;
    e1 = parity(x & 0x55);
    e2 = parity(x & 0x66);
    e3 = parity(x & 0x78);
    err_pos = e1 + e2 * 2 + e3 * 4;
    x ^= 1 << err_pos >> 1;
    data = x;
    data &= 0x74;
    data += 4;
    data >>= 3;
    return data;
}

CPU x86 tự động tính toán chẵn lẻ của từng kết quả trung gian. Nó có một hướng dẫn chuyên dụng jpmà nhảy hoặc không nhảy tùy thuộc vào tính chẵn lẻ.

Nó không được chỉ định rõ ràng trong thử thách, nhưng đặc tính tiện lợi của mã hamming là bạn có thể hiểu các bit chẵn lẻ là số nhị phân và con số này cho biết bit nào bị hỏng trong quá trình truyền. Trên thực tế, con số này là 1 dựa trên, với 0 có nghĩa là không có lỗi truyền. Điều này được thực hiện bằng cách dịch chuyển 1 trái qua err_posrồi sang phải 1.

Sau khi sửa lỗi truyền, mã sắp xếp các bit dữ liệu theo thứ tự cần thiết. Mã được tối ưu hóa cho kích thước và ban đầu nó có thể không rõ ràng về cách thức hoạt động của nó. Để giải thích nó, tôi biểu thị bởi a, b, c, dcác bit dữ liệu, và bằng cách P, QRcác bit chẵn lẻ. Sau đó:

    data = x;     // d  c  b  R  a  Q  P
    data &= 0x74; // d  c  b  0  a  0  0
    data += 4;    // d  c  b  a ~a  0  0
    data >>= 3;   // d  c  b  a

Nguồn hội ( fastcallquy ước, với đầu vào ecxvà đầu ra eax):

    xor eax, eax;
    inc eax;
    xchg eax, ecx;

    test al, 0x55;
    jp skip1;
    shl cl, 1;

skip1:
    test al, 0x66;
    jp skip2;
    shl cl, 2;

skip2:
    test al, 0x78;
    jp skip3;
    shl ecx, 4;

skip3:
    shr cl, 1;
    xor al, cl;

    and al, 0x74;
    add al, 4;
    shr al, 3;

    ret;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.