my version of @dis.sociat.ing's dollcode algorithm in python

minor refactoring & input validation

- better type hints
- input validation in decoding, raises ValueError when anything that isn't a
dollcode character is passed in input
- wrap main() logic in try/except block to neatly print errors and exit with
sys.exit(1)

+28 -21
+26 -19
main.py
··· 1 1 import argparse 2 + import sys 2 3 3 4 import pyperclip 4 5 ··· 7 8 8 9 9 10 # encodes input string into integer by using ord() & base256 10 - def encode_base256_int(input: str): 11 - result = 0 11 + def encode_base256_int(input: str) -> int: 12 + result: int = 0 12 13 13 14 for char in input: 14 15 result = (result * 256) + ord(char) ··· 17 18 18 19 19 20 # decodes input number back in char 20 - def decode_base256_int(num: int): 21 - output = "" 21 + def decode_base256_int(num: int) -> str: 22 + output: str = "" 22 23 23 24 while num > 0: 24 - char = chr(num % 256) 25 - output = char + output 25 + output = (chr(num % 256)) + output 26 26 num = num // 256 27 27 28 28 return output ··· 30 30 31 31 # converts encoded base256 int -> bijective base-3 numeration 32 32 # then inserts corresponding number (3, 1, 2) into output list 33 - def encode_dollcode(num: int): 33 + def encode_dollcode(num: int) -> list[str]: 34 34 output: list[str] = [] 35 35 window: int = num 36 + mod: int 36 37 37 38 while window > 0: 38 39 mod = window % BASE_NUM ··· 48 49 49 50 50 51 # decodes input dollcode -> integer 51 - def decode_dollcode(input: str): 52 + def decode_dollcode(input: str) -> int: 52 53 result: int = 0 53 54 54 55 for char in input: 55 - if char == DOLLCODE_CHARS[0]: 56 + if char not in DOLLCODE_CHARS: 57 + raise ValueError(f"Invalid character '{char}' in input") 58 + elif char == DOLLCODE_CHARS[0]: 56 59 result = (result + 1) * BASE_NUM 57 60 else: 58 61 result = result * BASE_NUM + DOLLCODE_CHARS.index(char) ··· 63 66 def main(command: str, input: str, copy: bool): 64 67 result: str = "" 65 68 66 - if command == "decode": 67 - result = decode_base256_int(decode_dollcode(input)) 68 - else: 69 - encoded_dollcode = encode_dollcode(encode_base256_int(input)) 70 - result = "".join(encoded_dollcode) 69 + try: 70 + if command == "decode": 71 + result = decode_base256_int(decode_dollcode(input)) 72 + else: 73 + encoded_dollcode = encode_dollcode(encode_base256_int(input)) 74 + result = "".join(encoded_dollcode) 71 75 72 - if copy: 73 - pyperclip.copy(result) 74 - print(f"{result} -> 📋 copied!") 75 - else: 76 - print(result) 76 + if copy: 77 + pyperclip.copy(result) 78 + print(f"{result} -> 📋 copied!") 79 + else: 80 + print(result) 81 + except ValueError as e: 82 + print(f"Error: {e}") 83 + sys.exit(1) 77 84 78 85 79 86 if __name__ == "__main__":
+1 -1
pyproject.toml
··· 1 1 [project] 2 2 name = "dollcode" 3 - version = "1.0.0" 3 + version = "1.0.1" 4 4 description = "converts input into dollcode" 5 5 readme = "README.md" 6 6 requires-python = ">=3.13"
+1 -1
uv.lock
··· 4 4 5 5 [[package]] 6 6 name = "dollcode" 7 - version = "1.0.0" 7 + version = "1.0.1" 8 8 source = { virtual = "." } 9 9 dependencies = [ 10 10 { name = "pyperclip" },