แก้ไขข้อผิดพลาดโดยใช้ Hamming (7,4)


19

รหัส Hamming (7,4) กลับไปที่ปี 1950 ก่อนหน้านั้น Richard Hamming ทำงานเป็นนักคณิตศาสตร์ที่ Bell Labs ทุกวันศุกร์ Hamming ตั้งค่าเครื่องคำนวณเพื่อทำการคำนวณแบบต่อเนื่องและรวบรวมผลลัพธ์ในวันจันทร์ถัดไป การใช้การตรวจสอบแบบพาริตี้ทำให้เครื่องเหล่านี้สามารถตรวจจับข้อผิดพลาดในระหว่างการคำนวณได้ ผิดหวังเพราะเขาได้รับข้อความแสดงข้อผิดพลาดบ่อยเกินไป Hamming ตัดสินใจปรับปรุงการตรวจจับข้อผิดพลาดและค้นพบรหัส Hamming ที่มีชื่อเสียง

กลไกของ Hamming (7,4)

เป้าหมายของรหัส Hamming คือการสร้างชุดของบิตพาริตี้ที่ทับซ้อนกันเช่นมีข้อผิดพลาดบิตเดียว (หนึ่งบิตพลิก) ในบิตข้อมูลหรือบิตพาริตี้สามารถตรวจพบและแก้ไขได้ เฉพาะในกรณีที่มีข้อผิดพลาดหลายอย่างรหัสแฮมมิงไม่สามารถกู้คืนข้อมูลดั้งเดิมได้ อาจไม่สังเกตเห็นข้อผิดพลาดเลยหรือแม้แต่แก้ไขให้ถูกต้อง ดังนั้นในความท้าทายนี้เราจะจัดการกับข้อผิดพลาดบิตเดียวเท่านั้น

ตัวอย่างของรหัส Hamming เราจะดูรหัส Hamming (7,4) นอกจากนี้ในข้อมูล 4 บิตd1, d2, d3, d4จะใช้ 3 บิตพาริตีp1, p2, p3ซึ่งคำนวณโดยใช้สมการต่อไปนี้:

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

codeword ที่เกิด (ข้อมูล + ความเท่าเทียมกันบิต) p1 p2 d1 p3 d2 d3 d4จะอยู่ในรูป

การตรวจจับข้อผิดพลาดทำงานด้วยวิธีต่อไปนี้ คุณคำนวณบิตพาริตีอีกครั้งและตรวจสอบว่าตรงกับบิตแพริตีที่ได้รับ ในตารางต่อไปนี้คุณจะเห็นได้ว่าข้อผิดพลาดทุกบิตเดียวให้ผลการจับคู่ที่แตกต่างกันของบิตพาริตี้ ดังนั้นทุกข้อผิดพลาดบิตเดียวสามารถแปลและแก้ไข

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

ตัวอย่าง

1011ให้ข้อมูลของคุณจะ บิตเท่าเทียมกันมีp1 = 1 + 0 + 1 = 0, และp2 = 1 + 1 + 1 = 1 p3 = 0 + 1 + 1 = 0รวมข้อมูลและความเท่าเทียมกันบิตและคุณได้รับ 0110011codeword

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

ให้พูดระหว่างการส่งหรือการคำนวณบิตที่ 6 (= บิตที่ 3 ข้อมูล) พลิก 0110001คุณได้รับคำ 1001ข้อมูลที่ได้รับการกล่าวหาว่าเป็น คุณคำนวณบิตเท่าเทียมกันอีกครั้งp1 = 1 + 0 + 1 = 0, ,p2 = 1 + 0 + 1 = 0 p3 = 0 + 0 + 1 = 1เฉพาะp1ตรงกับความเท่าเทียมกันของบิต 0110001codeword ดังนั้นจึงเกิดข้อผิดพลาด ดูตารางข้างต้นบอกเราว่ามีข้อผิดพลาดเกิดขึ้นd3และคุณสามารถกู้คืนข้อมูลต้นฉบับ1011ได้

ท้าทาย:

เขียนฟังก์ชั่นหรือโปรแกรมที่ได้รับคำ (7 บิต) หนึ่งในบิตอาจผิดและกู้คืนข้อมูลต้นฉบับ การป้อนข้อมูล (ผ่าน STDIN อาร์กิวเมนต์บรรทัดคำสั่งแจ้งหรือฟังก์ชั่นการโต้แย้ง) รูปแบบอาจจะเป็นสตริง"0110001", รายการหรืออาร์เรย์[0, 1, 1, 0, 0, 0, 1]หรือจำนวนเต็มใน 0b0110001 = 49MSB p1 p2 d1 p3 d2 d3 d4ตามที่อธิบายไว้ข้างต้นคำสั่งของการป้อนข้อมูลที่เป็น เอาท์พุท (ผ่านค่าตอบแทนหรือ STDOUT) จะต้องมีรูปแบบเดียวกัน d1 d2 d3 d4แต่ในการสั่งซื้อ ส่งคืน / ส่งออกข้อมูล 4 บิตเท่านั้น

นี่คือรหัสกอล์ฟ ดังนั้นรหัสที่สั้นที่สุดชนะ

กรณีทดสอบ:

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
มีเหตุผลพิเศษหรือไม่ที่จะให้บิตพาริตีสุดท้ายหลังจากบิตข้อมูลแรก?
xnor

2
@ xnor ในทางคณิตศาสตร์มันไม่ได้สร้างความแตกต่างใด ๆ ซึ่งตำแหน่งที่บิตพาริตี้เป็น ในอดีตพวกเขาจะถูกวางไว้ในตำแหน่งของพลังของทั้งสอง เช่น Hamming (15,11) มีบิตพาริตี้ที่ตำแหน่ง 1, 2, 4 และ 8
Jakube

4
@xnor หากคุณใช้เวลา[is_p3_wrong][is_p2_wrong][is_p1_wrong]ในฐานสองมันจะให้ตำแหน่งของบิตที่ไม่ถูกต้องในคำว่า (ขึ้นอยู่กับตารางในคำถาม) ซึ่งอาจเป็นประโยชน์สำหรับอัลกอริทึมบางอย่าง
randomra

ดีมาก :) เมื่อคุณเขียน "เขียนฟังก์ชั่นหรือโปรแกรมที่ได้รับคำ (7 บิต) หนึ่งในนั้นอาจจะผิด [... ]" ฉันคิดว่าคุณหมายถึงหนึ่งในบิตอาจผิด แต่คุณ จริง ๆ แล้วพูดคำใดคำหนึ่งอาจจะ

@ Lembik แน่นอนชี้แจง
Jakube

คำตอบ:


6

อ็อกเทฟ, 70 66 55 ไบต์

ฟังก์ชั่นFนี้ตั้งค่าการถอดรหัสเมทริกซ์Hค้นหาข้อผิดพลาดและแก้ไขตำแหน่งของข้อผิดพลาด (ถ้ามี) จากนั้นจะส่งคืนบิตข้อมูลที่ถูกต้อง อินพุตเป็นเวกเตอร์แถวมาตรฐาน

@Jakube แนะนำให้ใช้ Octave แทน Matlab ซึ่งคุณสามารถใช้ indices ในการแสดงออกซึ่งทำให้ทั้ง 11 ไบต์สั้นลงอีกครั้ง:

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

ต่อไปนี้เป็นทางออกที่สั้นที่สุดในMatlabเนื่องจากคุณไม่สามารถใช้การจัดทำดัชนีกับนิพจน์ได้โดยตรง (ใช้งานได้ใน Octave ด้วยเช่นกัน) สามารถแทนที่การเพิ่ม / mod2 ด้วยxor:

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

เก่า:

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

ขอบคุณ แต่นี้ไม่ได้ทำงานที่น่าเสียดายที่คุณเท่านั้นที่สามารถเข้าถึงตัวแปรว่าวิธีการ ...
flawr

1
ยังไม่ได้ติดตั้งโปรแกรม MATLAB ผมใช้เฉพาะhttp://octave-online.net/ที่มันทำงาน อาจจะเปลี่ยนภาษา
Jakube

โอ้ฉันสงสัยว่าอ็อกเทฟทั้งคู่สามารถทำได้ แต่แล้วฉันจะเปลี่ยนภาษาแน่นอนขอบคุณมาก!
ข้อบกพร่อง

14

Piet 50x11 = 550

ป้อนคำอธิบายรูปภาพที่นี่

ขนาดของ codel คือ 15 ไม่ต้องกังวลเกี่ยวกับขนาด แต่มันผ่านการทดสอบทั้งหมด


4
ฉันชอบสิ่งนี้เพราะบริบทของปัญหา

1
@Optimizer "codel size" เป็นหลักปัจจัยการขยายของโปรแกรม piet ที่นี่แต่ละพิกเซลเชิงตรรกะ (หรือ codel) ได้รับการขยายเป็นบล็อก 15x15 เพื่อให้มองเห็นได้ง่ายขึ้น นั่นคือสิ่งที่ฉันหมายถึงไม่ใช่ "ขนาดรหัส"
captncraig


8

Python, 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

ใช้อินพุตและเอาต์พุตเป็นตัวเลขโดยมีบิตนัยสำคัญน้อยที่สุดทางด้านขวา

แทนที่จะพยายามกู้คืนข้อผิดพลาดเราเพียงลองเข้ารหัสทุกข้อความที่เป็นไปได้nตั้งแต่ 0 ถึง 15 จนกว่าเราจะได้รับการเข้ารหัสที่อยู่ห่างจากที่ได้รับเพียงเล็กน้อย การเรียกซ้ำจะเพิ่มขึ้นเรื่อย ๆnจนกระทั่งพบที่ทำงานและส่งคืน แม้ว่าจะไม่มีการยกเลิกอย่างชัดเจน แต่จะต้องจบภายใน 16 ลูป

นิพจน์(n&8)*14^(n&4)*19^(n&2)*21^n%2*105ใช้เมทริกซ์ Hamming bitwise

เพื่อตรวจสอบข้อผิดพลาดเดียวเรา XOR ข้อความที่กำหนดให้มีการคำนวณอย่างใดอย่างหนึ่งที่จะได้รับeและตรวจสอบว่าเป็นอำนาจของทั้งสอง (หรือ 0) e&~-e==0กับบิตเคล็ดลับคลาสสิก แต่เราไม่สามารถกำหนดให้ตัวแปรeภายในแลมบ์ดาได้และเราอ้างถึงมันสองครั้งในนิพจน์นี้ดังนั้นเราจึงแฮ็คที่จะส่งผ่านมันเป็นอาร์กิวเมนต์ที่เป็นทางเลือกสำหรับขั้นตอนเรียกซ้ำ


7

JavaScript (ES6), 92 87 81

รับฟังก์ชั่นและการคืนค่าจำนวนเต็มใน MSB
การใช้งานนั้นตรงไปตรงมาตามความคิดเห็น @randomra:

  • Calc p3wrong | p2wrong | p1wrong (บรรทัด 2,3,4)
  • ใช้เป็นหน้ากากเพื่อพลิกบิตที่ไม่ถูกต้อง (บรรทัดที่ 1)
  • จากนั้นส่งคืนบิตข้อมูล (บรรทัดสุดท้าย)
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

ทดสอบในคอนโซล Frefox / FireBug

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

เอาท์พุต

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

1
ฉันชอบโซลูชันการทำงานระดับบิตขนาดกะทัดรัดของคุณจริง ๆ =)
ข้อผิดพลาด

4

Python 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)

อักขระหลายตัวเป็น ASCII ที่ไม่สามารถพิมพ์ได้ดังนั้นนี่คือเวอร์ชันที่หลีกเลี่ยง:

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)

อินพุตและเอาต์พุตไปยังฟังก์ชันทำเป็นจำนวนเต็ม

ฉันใช้ประโยชน์จากความจริงที่ว่าจำนวนข้อความที่ถูกต้องมีเพียง 16 ข้อความและเข้ารหัสยากทั้งหมด จากนั้นฉันลองพลิกบิตที่แตกต่างกันจนกว่าฉันจะได้หนึ่งในนั้น


3

Haskell, 152 ไบต์

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

การใช้งาน: a (1,1,1,1,0,1,1)ผลลัพธ์ใด(1,1,1,1)

ทางออกที่ตรงไปตรงมา: หากp<x>ไม่ตรงกันให้ตั้งค่าบิต<x>เป็นตัวเลข ถ้าจำนวนนี้เป็น3, 5, 6หรือพลิกที่สอดคล้องกัน7d<y>


คุณสามารถเพิ่มคำแนะนำเพิ่มเติมเกี่ยวกับวิธีการเรียกรหัสของคุณได้ (ตัวอย่างเช่นการใช้คอมไพเลอร์ออนไลน์เช่นideone.com ) ฉันได้รับข้อผิดพลาดแปลก ๆ อยู่เสมอ (น่าจะเป็นความผิดของฉัน)
Jakube

@Jakube: บันทึกรหัสลงในไฟล์พูดhamming.hsและโหลดลงใน ghci Haskell ghci hamming.hsREPL: เรียกใช้ฟังก์ชันaตามที่อธิบายไว้ข้างต้น ล่าม haskell ออนไลน์เดียวที่ฉันรู้จัก ( tryhaskell.org ) ต้องใช้โค้ดเพิ่มเติม:let a(p,q, ... 2-y in a (1,1,1,1,0,1,1)
nimi

3

รหัสเครื่อง IA-32 ขนาด 36 ไบต์

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

รหัส C ที่เทียบเท่ากัน:

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;
}

x86 CPU คำนวณความเท่าเทียมกันของผลลัพธ์กลางแต่ละรายการโดยอัตโนมัติ มันมีคำสั่งเฉพาะjpที่กระโดดหรือไม่กระโดดขึ้นอยู่กับความเท่าเทียมกัน

มันไม่ได้ระบุอย่างชัดเจนในการท้าทาย แต่คุณสมบัติที่สะดวกของรหัสแฮมมิงคือคุณสามารถตีความบิตพาริตีเป็นเลขฐานสองและหมายเลขนี้บ่งชี้ว่าบิตใดเสียในระหว่างการส่ง ที่จริงแล้วตัวเลขนี้เป็นแบบอิง 1 โดยที่ 0 หมายถึงไม่มีข้อผิดพลาดในการส่ง นี้จะดำเนินการโดยการขยับ 1 ซ้ายจากนั้นทางerr_pos1

หลังจากแก้ไขข้อผิดพลาดในการส่งรหัสจะจัดเรียงบิตข้อมูลตามลำดับที่ต้องการ รหัสได้รับการปรับให้เหมาะสมกับขนาดและอาจไม่ชัดเจนในตอนแรกว่ามันทำงานอย่างไร ที่จะอธิบายมันฉันใช้แสดงโดยa, b, c, dบิตข้อมูลและโดยP, QและRบิตเท่าเทียมกัน แล้ว:

    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

แหล่งประกอบ ( fastcallแบบแผนพร้อมอินพุตecxและเอาต์พุต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;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.