Last active
May 2, 2021 23:58
-
-
Save timeopochin/cffef82b3f659b937bd8a1c5acc58a04 to your computer and use it in GitHub Desktop.
A Dozenal Reverse Polish Calculator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A reverse polish calculator for the dozenal system | |
def dozToDec(doz): | |
dozenal = None | |
if '.' in doz: | |
doz, dozenal = doz.split('.') | |
sum = 0 | |
for i in range(len(doz)): | |
addition = DOZ_DIGITS.index(doz[len(doz) - i - 1]) | |
for _ in range(i): | |
addition *= 12 | |
sum += addition | |
if dozenal: | |
for i in range(len(dozenal)): | |
addition = DOZ_DIGITS.index(dozenal[i]) | |
for _ in range(i + 1): | |
addition /= 12 | |
sum += addition | |
return sum | |
def decimalToDoz(decimal): | |
doz = "" | |
for i in range(DPRCSN): | |
doz += DOZ_DIGITS[int(decimal*12)] | |
decimal = decimal*12 % 1 | |
if decimal < 1/(10**(DPRCSN - i)): | |
break | |
return doz | |
def decToDoz(dec): | |
if type(dec) == complex: | |
real = decToDoz(dec.real) | |
imag = decToDoz(dec.imag) | |
return real + ' ' + imag + " i * +" | |
decimal = None | |
if dec % 1: | |
decimal = dec % 1 | |
dec = int(dec) | |
doz = "" | |
while dec > 0: | |
doz = DOZ_DIGITS[dec % 12] + doz | |
dec //= 12 | |
if decimal: | |
doz += '.' + decimalToDoz(decimal) | |
elif doz == "": | |
doz = "0" | |
return doz | |
def splitExpr(expr): | |
split = [] | |
num = "" | |
for char in expr: | |
if char in DOZ_DIGITS or (char == '.' and '.' not in num): | |
num += char | |
elif char in OPS + COMMANDS: | |
if len(num) > 0: | |
split.append(num) | |
num = "" | |
split.append(char) | |
elif char == ' ': | |
if len(num) > 0: | |
split.append(num) | |
num = "" | |
else: | |
print("Error: `{}` is not a valid syntax".format(char)) | |
return [] | |
if num: | |
split.append(num) | |
return split | |
def processExpr(stack, expr): | |
for item in splitExpr(expr): | |
if item in COMMANDS: | |
if item in "pd": | |
if len(stack) == 0: | |
print("Stack is empty") | |
elif item == 'p': | |
print(decToDoz(stack[-1])) | |
elif item == 'd': | |
print("{} ({})".format(decToDoz(stack[-1]), stack[-1])) | |
elif item == 'c': | |
stack.clear() | |
clearScreen() | |
elif item == 'q': | |
exit() | |
elif item in OPS: | |
if len(stack) < 2: | |
print("Not enough items in the stack: ignoring `{}`".format(item)) | |
else: | |
second = stack.pop() | |
first = stack[-1] | |
if item == '+': | |
result = first + second | |
elif item == '-': | |
result = first - second | |
elif item == '*': | |
result = first*second | |
elif item == '/': | |
result = first/second | |
elif item == '^': | |
result = first**second | |
stack[-1] = result | |
else: | |
stack.append(dozToDec(item)) | |
def clearScreen(): | |
print("\x1b[2J\x1b[1;1H") | |
DPRCSN = 12 | |
DOZ_DIGITS = "0123456789XE" | |
OPS = "+-*/^" | |
COMMANDS = "pdcq" | |
# TODO: implement constants | |
CONSTS = { | |
"$pi": 3.141592653589793, | |
"$e": 2.718281828459045 | |
} | |
if __name__ == "__main__": | |
stack = [] | |
while True: | |
expr = input() | |
processExpr(stack, expr) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment