|
@@ -1,50 +1,11 @@
|
|
|
#!/usr/bin/env python3
|
|
#!/usr/bin/env python3
|
|
|
import sys
|
|
import sys
|
|
|
|
|
+from collections import namedtuple
|
|
|
from operator import add, mul, floordiv, mod, eq
|
|
from operator import add, mul, floordiv, mod, eq
|
|
|
|
|
|
|
|
|
|
+Expr = namedtuple('Expr', 'opcode, left, right')
|
|
|
OPS = {'add': add, 'mul': mul, 'div': floordiv, 'mod': mod, 'eql': eq}
|
|
OPS = {'add': add, 'mul': mul, 'div': floordiv, 'mod': mod, 'eql': eq}
|
|
|
|
|
|
|
|
-class Expr:
|
|
|
|
|
- def __init__(self, opcode, left, right):
|
|
|
|
|
- self.opcode = opcode
|
|
|
|
|
- self.left = left
|
|
|
|
|
- self.right = right
|
|
|
|
|
-
|
|
|
|
|
- def reduce(self, conditions):
|
|
|
|
|
- lconst = isinstance(self.left, int)
|
|
|
|
|
- rconst = isinstance(self.right, int)
|
|
|
|
|
-
|
|
|
|
|
- if lconst and rconst:
|
|
|
|
|
- return int(OPS[self.opcode](self.left, self.right))
|
|
|
|
|
- elif lconst and self.opcode in ('add', 'mul', 'eql'):
|
|
|
|
|
- return Expr(self.opcode, self.right, self.left).reduce(conditions)
|
|
|
|
|
-
|
|
|
|
|
- if self.opcode == 'add':
|
|
|
|
|
- if self.right == 0:
|
|
|
|
|
- return self.left
|
|
|
|
|
- if self.left.opcode == 'add':
|
|
|
|
|
- right = self.left.right + self.right
|
|
|
|
|
- return Expr('add', self.left.left, right)
|
|
|
|
|
- elif self.opcode == 'mul':
|
|
|
|
|
- if self.right == 0:
|
|
|
|
|
- return 0
|
|
|
|
|
- if self.right == 1:
|
|
|
|
|
- return self.left
|
|
|
|
|
- elif self.opcode == 'eql':
|
|
|
|
|
- offset = self.left.right
|
|
|
|
|
- if rconst or offset > 9:
|
|
|
|
|
- return 0
|
|
|
|
|
- conditions.append((self.left.left.left, self.right.left, offset))
|
|
|
|
|
- return 1
|
|
|
|
|
- elif self.opcode == 'div':
|
|
|
|
|
- return self.left if self.right == 1 else self.left.left.left
|
|
|
|
|
- elif self.opcode == 'mod':
|
|
|
|
|
- if self.left.left.opcode == 'inp':
|
|
|
|
|
- return self.left
|
|
|
|
|
- return self.left.right
|
|
|
|
|
-
|
|
|
|
|
- return self
|
|
|
|
|
-
|
|
|
|
|
def parse(line):
|
|
def parse(line):
|
|
|
parts = line.split()
|
|
parts = line.split()
|
|
|
if len(parts) == 2:
|
|
if len(parts) == 2:
|
|
@@ -55,18 +16,50 @@ def parse(line):
|
|
|
operand = parts[2]
|
|
operand = parts[2]
|
|
|
return parts[0], parts[1], operand
|
|
return parts[0], parts[1], operand
|
|
|
|
|
|
|
|
-def input_conditions(program):
|
|
|
|
|
|
|
+def simplify(e, conditions):
|
|
|
|
|
+ lconst = isinstance(e.left, int)
|
|
|
|
|
+ rconst = isinstance(e.right, int)
|
|
|
|
|
+
|
|
|
|
|
+ if lconst and rconst:
|
|
|
|
|
+ return int(OPS[e.opcode](e.left, e.right))
|
|
|
|
|
+ elif lconst and e.opcode in ('add', 'mul', 'eql'):
|
|
|
|
|
+ return simplify(Expr(e.opcode, e.right, e.left), conditions)
|
|
|
|
|
+
|
|
|
|
|
+ if e.opcode == 'add':
|
|
|
|
|
+ if e.right == 0:
|
|
|
|
|
+ return e.left
|
|
|
|
|
+ if e.left.opcode == 'add':
|
|
|
|
|
+ return Expr('add', e.left.left, e.left.right + e.right)
|
|
|
|
|
+ elif e.opcode == 'mul':
|
|
|
|
|
+ if e.right == 0:
|
|
|
|
|
+ return 0
|
|
|
|
|
+ if e.right == 1:
|
|
|
|
|
+ return e.left
|
|
|
|
|
+ elif e.opcode == 'eql':
|
|
|
|
|
+ offset = e.left.right
|
|
|
|
|
+ if rconst or offset > 9:
|
|
|
|
|
+ return 0
|
|
|
|
|
+ conditions.append((e.left.left.left, e.right.left, offset))
|
|
|
|
|
+ return 1
|
|
|
|
|
+ elif e.opcode == 'div':
|
|
|
|
|
+ return e.left if e.right == 1 else e.left.left.left
|
|
|
|
|
+ elif e.opcode == 'mod':
|
|
|
|
|
+ return e.left if e.left.left.opcode == 'inp' else e.left.right
|
|
|
|
|
+
|
|
|
|
|
+ return e
|
|
|
|
|
+
|
|
|
|
|
+def input_conditions(nomad):
|
|
|
conditions = []
|
|
conditions = []
|
|
|
regs = {'w': 0, 'x': 0, 'y': 0, 'z': 0}
|
|
regs = {'w': 0, 'x': 0, 'y': 0, 'z': 0}
|
|
|
index = 0
|
|
index = 0
|
|
|
- for opcode, reg, operand in program:
|
|
|
|
|
|
|
+ for opcode, reg, operand in nomad:
|
|
|
if opcode == 'inp':
|
|
if opcode == 'inp':
|
|
|
regs[reg] = Expr('inp', index, None)
|
|
regs[reg] = Expr('inp', index, None)
|
|
|
index += 1
|
|
index += 1
|
|
|
else:
|
|
else:
|
|
|
if not isinstance(operand, int):
|
|
if not isinstance(operand, int):
|
|
|
operand = regs[operand]
|
|
operand = regs[operand]
|
|
|
- regs[reg] = Expr(opcode, regs[reg], operand).reduce(conditions)
|
|
|
|
|
|
|
+ regs[reg] = simplify(Expr(opcode, regs[reg], operand), conditions)
|
|
|
return conditions
|
|
return conditions
|
|
|
|
|
|
|
|
def modelnum(conditions, largest):
|
|
def modelnum(conditions, largest):
|