Spaces:
Sleeping
Sleeping
| def encode_hamming(bc): | |
| """ | |
| Hamming(7,4) encoding with an extra parity bit → SECDED (8,4). | |
| Can correct 1-bit errors AND detect 2-bit errors. | |
| """ | |
| new_bc = "" | |
| # Pad to multiple of 4 | |
| while len(bc) % 4 != 0: | |
| bc += '0' | |
| for i in range(0, len(bc), 4): | |
| group = bc[i:i + 4] | |
| p1 = int(group[0]) ^ int(group[1]) ^ int(group[3]) | |
| p2 = int(group[0]) ^ int(group[2]) ^ int(group[3]) | |
| p3 = int(group[1]) ^ int(group[2]) ^ int(group[3]) | |
| # Standard 7-bit Hamming block | |
| block = str(p1) + str(p2) + group[0] + str(p3) + group[1] + group[2] + group[3] | |
| # Extra overall parity bit for SECDED (detect 2-bit errors) | |
| overall_parity = 0 | |
| for bit in block: | |
| overall_parity ^= int(bit) | |
| block += str(overall_parity) | |
| new_bc += block | |
| return new_bc | |
| def decode_hamming(bc): | |
| """ | |
| SECDED (8,4) decoding: corrects 1-bit errors, detects 2-bit errors. | |
| Falls back gracefully on 2-bit errors by keeping the data as-is. | |
| """ | |
| decoded_output = "" | |
| # Determine block size: 8 for SECDED, 7 for legacy Hamming(7,4) | |
| # Auto-detect based on data length | |
| if len(bc) % 8 == 0: | |
| block_size = 8 | |
| elif len(bc) % 7 == 0: | |
| block_size = 7 | |
| else: | |
| # Try 8 first, fallback to 7 | |
| block_size = 8 if (len(bc) % 8 < len(bc) % 7) else 7 | |
| for i in range(0, len(bc), block_size): | |
| group = list(bc[i:i + block_size]) | |
| if len(group) < 7: | |
| break | |
| s1 = int(group[0]) ^ int(group[2]) ^ int(group[4]) ^ int(group[6]) | |
| s2 = int(group[1]) ^ int(group[2]) ^ int(group[5]) ^ int(group[6]) | |
| s3 = int(group[3]) ^ int(group[4]) ^ int(group[5]) ^ int(group[6]) | |
| syndrome = int(str(s3) + str(s2) + str(s1), 2) | |
| if block_size == 8 and len(group) == 8: | |
| # SECDED mode: check overall parity | |
| overall_parity = 0 | |
| for bit in group: | |
| overall_parity ^= int(bit) | |
| if syndrome == 0 and overall_parity == 0: | |
| # No error | |
| pass | |
| elif syndrome != 0 and overall_parity == 1: | |
| # Single-bit error → correct it | |
| error_pos = syndrome | |
| print(f"[!] Noise detected! Healing bit at position {error_pos}...") | |
| if error_pos <= 7: | |
| group[error_pos - 1] = '1' if group[error_pos - 1] == '0' else '0' | |
| elif error_pos == 8: | |
| # Error is in the parity bit itself, data is fine | |
| pass | |
| elif syndrome != 0 and overall_parity == 0: | |
| # 2-bit error detected → CANNOT correct, keep data as-is | |
| print(f"[!!] 2-bit error detected in block (syndrome={syndrome})! Cannot correct, keeping raw data.") | |
| elif syndrome == 0 and overall_parity == 1: | |
| # Error in the overall parity bit only, data is fine | |
| print(f"[~] Parity bit error only, data intact.") | |
| else: | |
| print(f"[+] Block OK") | |
| else: | |
| # Legacy Hamming(7,4) mode | |
| if syndrome == 0: | |
| print("[+] Block OK") | |
| else: | |
| error_pos = syndrome | |
| print(f"[!] Noise detected! Healing bit at position {error_pos}...") | |
| if group[error_pos - 1] == '0': | |
| group[error_pos - 1] = '1' | |
| else: | |
| group[error_pos - 1] = '0' | |
| # Extract the 4 data bits (positions 3, 5, 6, 7 = indices 2, 4, 5, 6) | |
| decoded_output += group[2] + group[4] + group[5] + group[6] | |
| return decoded_output | |
| if __name__ == '__main__': | |
| bc = "01010101" | |
| print(f"Original: {bc}") | |
| encoded = encode_hamming(bc) | |
| print(f"Encoded: {encoded} ({len(encoded)} bits, block size {len(encoded) // (len(bc) // 4)})") | |
| decoded = decode_hamming(encoded) | |
| print(f"Decoded: {decoded}") | |
| print(f"Match: {decoded == bc}") |