Skip to content

Instantly share code, notes, and snippets.

@segasai
Last active December 21, 2020 16:12
Show Gist options
  • Save segasai/81e48162825cbd8c94f616130d15c939 to your computer and use it in GitHub Desktop.
Save segasai/81e48162825cbd8c94f616130d15c939 to your computer and use it in GitHub Desktop.
day18
from enum import Enum
import sys
class State(Enum):
DEFAULT = -1
NUMBER = 1
PARENTHESIS = 2
OPERATOR = 3
class Operator(Enum):
MULT = 1
ADD = 2
class Number:
def __init__(self, val):
self.value = val
def __str__(self):
return 'NUM: %d' % (self.value)
class PAREN(Enum):
OPEN = 1
CLOSE = 2
def tokenize(S):
R = []
state = State.DEFAULT
par_state = 0
numbuf = ['']
for i, k in enumerate(S):
if k in '0123456789':
if state != State.NUMBER:
numbuf = [k]
state = State.NUMBER
else:
numbuf.append(k)
continue
else:
# closure of number
if state == State.NUMBER:
val = int(''.join(numbuf))
R.append(Number(val))
numbuf = ['']
if k in '()':
state = State.PARENTHESIS
if k == '(':
R.append(PAREN.OPEN)
par_state += 1
if k == ')':
R.append(PAREN.CLOSE)
par_state -= 1
assert (par_state >= 0)
continue
if k == '+':
R.append(Operator.ADD)
continue
if k == '*':
R.append(Operator.MULT)
continue
if k == ' ':
state = State.DEFAULT
continue
raise Exception('oops', k)
if state == State.NUMBER:
val = int(''.join(numbuf))
R.append(Number(val))
return R
def proc(listTokens):
#print("PROCESSING")
#for ll in listTokens:
# print(ll)
#print('END')
R = []
i = 0
# process parenthesis blocks replacing them
while True:
if i == len(listTokens):
break
if listTokens[i] == PAREN.OPEN:
# print('opening')
state = 1
for i1 in range(i + 1, len(listTokens)):
if listTokens[i1] == PAREN.OPEN:
state += 1
if listTokens[i1] == PAREN.CLOSE:
state -= 1
if state == 0:
R.append(Number(proc(listTokens[i + 1:i1])))
break
i = i1 + 1
continue
if listTokens[i] == PAREN.CLOSE:
# print(listTokens, i)
raise Exception('oops2')
R.append(listTokens[i])
i += 1
val = R[0].value
lastop = None
for v in R[1:]:
if lastop is None and isinstance(v, Operator):
lastop = v
continue
if lastop is not None and isinstance(v, Number):
if lastop == Operator.MULT:
val = val * v.value
if lastop == Operator.ADD:
val = val + v.value
lastop = None
return val
def doall(fname):
for ll in open(fname, 'r').read().split('\n'):
print(proc(tokenize(ll)))
if __name__ == '__main__':
S = sys.argv[1] # '1 + 2 * 3 + 4 * 5 + 6'
T = tokenize(S)
print(S)
print('TOKENS')
for a in T:
print(a)
print('----')
print(T)
R = proc(T)
print('RESULT')
print(R)
from enum import Enum
import copy
import sys
class State(Enum):
DEFAULT = -1
NUMBER = 1
PARENTHESIS = 2
OPERATOR = 3
class Operator(Enum):
MULT = 1
ADD = 2
class Number:
def __init__(self, val):
self.value = val
def __str__(self):
return 'NUM: %d' % (self.value)
class PAREN(Enum):
OPEN = 1
CLOSE = 2
def tokenize(S):
R = []
state = State.DEFAULT
par_state = 0
numbuf = ['']
for i, k in enumerate(S):
if k in '0123456789':
if state != State.NUMBER:
numbuf = [k]
state = State.NUMBER
else:
numbuf.append(k)
continue
else:
# closure of number
if state == State.NUMBER:
val = int(''.join(numbuf))
R.append(Number(val))
numbuf = ['']
if k in '()':
state = State.PARENTHESIS
if k == '(':
R.append(PAREN.OPEN)
par_state += 1
if k == ')':
R.append(PAREN.CLOSE)
par_state -= 1
assert (par_state >= 0)
continue
if k == '+':
R.append(Operator.ADD)
continue
if k == '*':
R.append(Operator.MULT)
continue
if k == ' ':
state = State.DEFAULT
continue
raise Exception('oops', k)
if state == State.NUMBER:
val = int(''.join(numbuf))
R.append(Number(val))
return R
def proc(listTokens):
R = []
i = 0
# process parenthesis blocks replacing them
while True:
if i == len(listTokens):
break
if listTokens[i] == PAREN.OPEN:
# print('opening')
state = 1
for i1 in range(i + 1, len(listTokens)):
if listTokens[i1] == PAREN.OPEN:
state += 1
if listTokens[i1] == PAREN.CLOSE:
state -= 1
if state == 0:
R.append(Number(proc(listTokens[i + 1:i1])))
break
i = i1 + 1
continue
if listTokens[i] == PAREN.CLOSE:
# print(listTokens, i)
raise Exception('oops2')
R.append(listTokens[i])
i += 1
R1 = copy.copy(R)
for curop in [Operator.ADD, Operator.MULT]:
lastval = R1[0]
accum = False
R2 = []
#print(" PROCESSING")
#for ll in R1:
# print(ll)
#print('END')
for v in R1[1:]:
if isinstance(v, Operator):
if v == curop:
accum = True
else:
accum = False
R2.append(lastval)
R2.append(v)
if isinstance(v, Number):
if accum:
if curop == Operator.MULT:
val = lastval.value * v.value
if curop == Operator.ADD:
val = lastval.value + v.value
lastval = Number(val)
else:
lastval = v
R2.append(lastval)
R1 = R2
ret = R2[0].value
#print('RESULT', ret)
return ret
def doall(fname):
for ll in open(fname, 'r').read().split('\n'):
print(proc(tokenize(ll)))
if __name__ == '__main__':
S = sys.argv[1] # '1 + 2 * 3 + 4 * 5 + 6'
T = tokenize(S)
print(S)
print('TOKENS')
for a in T:
print(a)
print('----')
print(T)
R = proc(T)
print('RESULT')
print(R)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment