Skip to content

Commit 64f3ade

Browse files
committed
Implement Hamming code
1 parent 0d34235 commit 64f3ade

File tree

5 files changed

+55
-0
lines changed

5 files changed

+55
-0
lines changed

hamming/__init__.py

Whitespace-only changes.

hamming/src/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from .lib import decode, encode
2+
3+
__all__ = ["encode", "decode"]

hamming/src/lib.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from functools import reduce
2+
from math import ceil, log
3+
4+
5+
def encode(value: str) -> str:
6+
code = [0] + [
7+
int(i) for i in "".join(format(i, "b") for i in bytearray(value, "utf8"))
8+
]
9+
length = len(code) - 1
10+
11+
r = 1
12+
while 2**r < length + r + 1:
13+
r += 1
14+
15+
for i in range(1, length + r + 1):
16+
# check if power of 2
17+
if log(i, 2) == ceil(log(i, 2)):
18+
code.insert(i, 0)
19+
20+
for i in range(0, r):
21+
x = 2**i
22+
23+
for j in range(1, len(code)):
24+
if ((j >> i) & 1) == 1 and x != j:
25+
code[x] = code[x] ^ code[j]
26+
27+
return "".join(str(i) for i in code)
28+
29+
30+
def decode(value: str) -> tuple[str, int]:
31+
code = [int(i) for i in value]
32+
33+
def decoded():
34+
for i in range(1, len(code)):
35+
if log(i, 2) != ceil(log(i, 2)):
36+
yield str(code[i])
37+
38+
decoded = "".join(decoded())
39+
position = reduce(lambda x, y: x ^ y, [n for n, bit in enumerate(code) if bit])
40+
41+
if position == 0:
42+
position = -1
43+
44+
return (decoded, position)

hamming/tests/__init__.py

Whitespace-only changes.

hamming/tests/test.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from ..src import decode, encode
2+
3+
4+
def test_basic():
5+
encoded = encode("abc")
6+
_, error = decode(encoded)
7+
8+
assert error == -1

0 commit comments

Comments
 (0)