diff --git a/alphabetseq b/alphabetseq new file mode 100755 index 0000000..f87026e --- /dev/null +++ b/alphabetseq @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import itertools +import sys + + +def decimal_to_alphabet(n: int, alphabet: str) -> str: + if n == 0: + return alphabet[0] + base = len(alphabet) + digits = [] + while n: + digits.append(alphabet[n % base]) + n //= base + return ''.join(digits[::-1]) + + +def alphabet_to_decimal(s: str, alphabet: str) -> int: + base = len(alphabet) + l = len(s) + return sum(alphabet.index(s[l - 1 - i]) * base ** i for i in range(l)) + + +def test(): + assert alphabet_to_decimal('ff', '0123456789abcdef') == 255 + assert alphabet_to_decimal('100', '0123456789abcdef') == 256 + assert decimal_to_alphabet(255, '0123456789abcdef') == 'ff' + assert decimal_to_alphabet(256, '0123456789abcdef') == '100' + assert decimal_to_alphabet(0, '0123456789') == '0' + + +if __name__ == '__main__': + if len(sys.argv) == 2 and sys.argv[1] == '--test': + test() + elif len(sys.argv) == 4 or (len(sys.argv) == 5 and sys.argv[2] == '--decimal'): + if len(sys.argv) == 4: + alphabet = sys.argv[1] + start, stop = map(lambda x: alphabet_to_decimal(x, alphabet), sys.argv[2:]) + else: + alphabet = sys.argv[1] + start, stop = map(int, sys.argv[3:]) + for i in range(start, stop + 1): + try: + sys.stdout.write(decimal_to_alphabet(i, alphabet) + '\n') + except (BrokenPipeError, IOError): + try: + sys.stdout.close() + except IOError: + pass + break + else: + print('Usage: alphabetseq ALPHABET [--decimal] START STOP', file = sys.stderr) + print('Generates the sequence from START to STOP (inclusive) using ALPHABET', file = sys.stderr) + print('By default, START and STOP are expressed in ALPHABET. With --decimal, they are treated as decimal values instead.', file = sys.stderr) + print('`alphabetseq 0123456789 $N $M` is equivalent to `seq $N $M`.', file = sys.stderr)