Skip to content

Instantly share code, notes, and snippets.

@quxiaowei
Last active June 16, 2017 10:26
Show Gist options
  • Save quxiaowei/ad5846ec6d4a99bb1bdbf5d4a85386c3 to your computer and use it in GitHub Desktop.
Save quxiaowei/ad5846ec6d4a99bb1bdbf5d4a85386c3 to your computer and use it in GitHub Desktop.
A humble calculator
import re
from copy import deepcopy
import operator
RE_NUM = re.compile('\s*([-+]?\d+(\.\d+)?)')
def number(word):
result = RE_NUM.match(word)
groups = result.groups()
num_str = result.groups[0]
if groups[1] is not None:
return float(num_str)
else:
return int(num_str)
class Chain:
_dict = {
'+': {'w':2, 'func': operator.add},
'-': {'w':2, 'func': operator.sub},
'*': {'w':4, 'func': operator.mul},
'/': {'w':4, 'func': operator.truediv},
'(': {'w':5, 'func': None},
')': {'w':-5, 'func': None}
}
_border = {'w': -100000, 'func': None}
def __init__(self, raw_string):
self._operators = []
self._num = []
base = 0
for i in raw_string.split():
if i in set(Chain._dict.keys()):
if i in set('()'):
base = base + Chain._dict[i]['w']
else:
oper = deepcopy(Chain._dict[i])
oper['w'] += base
self._operators.append(oper)
else:
self._num.append(number(i))
if base != 0:
pass #error
def __len__(self):
return len(self._operators)
def __getitem__(self, i):
if i < 0 or i >= len(self):
return Chain._border
else:
return self._operators[i]
def reduce_chain(self, i):
self._num[i] = \
self._operators[i]['func'](self._num[i], self._num[i+1])
del(self._operators[i])
del(self._num[i+1])
def result(self):
return self._num
i = 0
raw_string = '1 + 2 + ( 2 * 3 + 1 ) * 2 + 2 * 3 + ( 1 + 2 * 8 )'
chain = Chain(raw_string)
while len(chain) != 0:
j = max((i, i-1, i+1), key=lambda a: chain[a]['w'])
if i == j:
chain.reduce_chain(i)
if i == len(chain): # not necessary but ...
i = i-1
else:
i = j
print(chain.result())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment