import string class B40: cset = "".join(sorted("\0" + string.digits + string.ascii_uppercase + " .,")) assert len(cset) == 40 def dec(self, bytes): i = 0 j = 0 while True: if j == 0: d = bytes[i] * 256 if i + 1 < len(bytes): d += bytes[i+1] print(f"[DEC] {d: 5}") i += 2 j = 3 print(d, end=" ") d = d * 40 # 24 bit temporary result top = d >> 16 d = d & 0xffff print(d, top, end=" ") if top == 0: break c = self.cset[top] print(repr(c)) yield c j -= 1 print() def enc(self, message): message = [self.cset.find(c) for c in message.upper()] assert not any(i==-1 for i in message) print(len(message)) while len(message) % 3: message.append(0) for i in range(0, len(message), 3): trio = message[i:i+3][::-1] d = 0 for c in trio: d = (d + (c << 16) + 39) // 40 print(f"{c:2} {repr(self.cset[c]):5}", f"{d:5d}", end=" ") print(f" {d: 5}") assert 0 <= d < 65536 yield d >> 8 yield d & 0xff yield 0 b40 = B40() encoded = list(b40.enc("hello world 12,345.67")) print(encoded) decoded = list(b40.dec(encoded)) print(decoded) print(repr(b40.cset))