my version of @dis.sociat.ing's dollcode algorithm in python
1import argparse
2import sys
3
4import pyperclip
5
6DOLLCODE_CHARS = ("▌", "▖", "▘")
7BASE_NUM = 3
8
9
10# encodes input string into integer by using ord() & base256
11def encode_base256_int(input: str) -> int:
12 result: int = 0
13
14 for char in input:
15 result = (result * 256) + ord(char)
16
17 return result
18
19
20# decodes input number back in char
21def decode_base256_int(num: int) -> str:
22 output: str = ""
23
24 while num > 0:
25 output = (chr(num % 256)) + output
26 num = num // 256
27
28 return output
29
30
31# converts encoded base256 int -> bijective base-3 numeration
32# then inserts corresponding number (3, 1, 2) into output list
33def encode_dollcode(num: int) -> list[str]:
34 output: list[str] = []
35 window: int = num
36 mod: int
37
38 while window > 0:
39 mod = window % BASE_NUM
40
41 if mod == 0:
42 window = (window - BASE_NUM) // BASE_NUM
43 else:
44 window = (window - mod) // BASE_NUM
45
46 output.insert(0, DOLLCODE_CHARS[mod])
47
48 return output
49
50
51# decodes input dollcode -> integer
52def decode_dollcode(input: str) -> int:
53 result: int = 0
54
55 for char in input:
56 if char not in DOLLCODE_CHARS:
57 raise ValueError(f"Invalid character '{char}' in input")
58 elif char == DOLLCODE_CHARS[0]:
59 result = (result + 1) * BASE_NUM
60 else:
61 result = result * BASE_NUM + DOLLCODE_CHARS.index(char)
62
63 return result
64
65
66def main(command: str, input: str, copy: bool):
67 result: str = ""
68
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)
75
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)
84
85
86if __name__ == "__main__":
87 parser = argparse.ArgumentParser(description="converts input into dollcode")
88 subparsers = parser.add_subparsers(dest="command", required=True)
89
90 # encode subcommand
91 encode_parser = subparsers.add_parser("encode", help="encode text to dollcode")
92 encode_parser.add_argument("input", type=str, help="text to encode")
93 encode_parser.add_argument(
94 "-c", action="store_true", help="copy output to clipboard"
95 )
96
97 # decode subcommand
98 decode_parser = subparsers.add_parser("decode", help="decode dollcode to text")
99 decode_parser.add_argument("input", type=str, help="dollcode to decode")
100 decode_parser.add_argument(
101 "-c", action="store_true", help="copy output to clipboard"
102 )
103
104 args = parser.parse_args()
105 main(args.command, args.input, args.c)