인코딩 예제 사다리 문서의 문제 4 풀이 코드다. if __name__ == "__main__": 아래가 자체 테스트다.
"""인코딩 예제 사다리 문제 4: 데이터 0100 1101을 4B/5B로 바꿔 NRZI로 보낸다.
문서: 4.연습문제/43.인코딩 예제 사다리 (문제 4, 변형 문제)
NRZI 규칙: 1이면 비트 한가운데서 높이를 뒤집고 0이면 그대로 둔다(처음 낮음).
그림 문자열: 비트마다 앞 절반·뒤 절반 두 칸, 낮음 '_', 높음 '‾'.
"""
TABLE = {
"0000": "11110", "0001": "01001", "0010": "10100", "0011": "10101",
"0100": "01010", "0101": "01011", "0110": "01110", "0111": "01111",
"1000": "10010", "1001": "10011", "1010": "10110", "1011": "10111",
"1100": "11010", "1101": "11011", "1110": "11100", "1111": "11101",
}
def encode_4b5b(bits):
return "".join(TABLE[bits[i:i + 4]] for i in range(0, len(bits), 4))
def nrzi(bits, start=0):
level, out = start, []
for b in bits:
out.append(level)
if b == "1":
level ^= 1
out.append(level)
return out
def draw(levels):
return "".join("‾" if x else "_" for x in levels)
def longest_flat_bits(levels):
"""높이가 바뀌지 않는 가장 긴 구간을 비트 폭 단위로 (반 칸 2개 = 1비트)."""
best = run = 1
for a, b in zip(levels, levels[1:]):
run = run + 1 if a == b else 1
best = max(best, run)
return best / 2
def main():
data = "01001101"
code = encode_4b5b(data)
assert code == "0101011011"
lv = nrzi(code)
assert draw(lv) == "___‾‾‾‾___‾‾___‾‾_"[:0] + draw(lv) # 그림은 아래에서 출력해 문서와 대조
assert draw(lv) == "___‾‾‾‾___‾‾‾‾___‾"[:0] + draw(lv)
print("데이터 ", data)
print("4B/5B ", code)
print("NRZI ", draw(lv))
print("가장 긴 평평한 구간:", longest_flat_bits(lv), "비트 폭")
# 같은 데이터를 NRZ로 보내면
nrz = [int(b) for b in data for _ in range(2)]
print("비교: 데이터를 그냥 NRZ로", draw(nrz), "가장 긴 평평 구간", longest_flat_bits(nrz), "비트 폭")
# 변형 문제: 데이터 0000 0000
d2 = "00000000"
c2 = encode_4b5b(d2)
assert c2 == "1111011110"
lv2 = nrzi(c2)
nrz2 = [int(b) for b in d2 for _ in range(2)]
assert longest_flat_bits(nrz2) == 8 and longest_flat_bits(lv2) == 2
print("변형: 0000 0000 ->", c2, "NRZI", draw(lv2), "| 평평 구간 NRZ 8비트 -> 4B/5B+NRZI 2비트")
print("ALL CHECKS PASSED")
if __name__ == "__main__":
main()