Taddeus Kroes 4 년 전
부모
커밋
20524e769f
1개의 변경된 파일37개의 추가작업 그리고 44개의 파일을 삭제
  1. 37 44
      2021/24_alu.py

+ 37 - 44
2021/24_alu.py

@@ -1,50 +1,11 @@
 #!/usr/bin/env python3
 import sys
+from collections import namedtuple
 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}
 
-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):
     parts = line.split()
     if len(parts) == 2:
@@ -55,18 +16,50 @@ def parse(line):
         operand = parts[2]
     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 = []
     regs = {'w': 0, 'x': 0, 'y': 0, 'z': 0}
     index = 0
-    for opcode, reg, operand in program:
+    for opcode, reg, operand in nomad:
         if opcode == 'inp':
             regs[reg] = Expr('inp', index, None)
             index += 1
         else:
             if not isinstance(operand, int):
                 operand = regs[operand]
-            regs[reg] = Expr(opcode, regs[reg], operand).reduce(conditions)
+            regs[reg] = simplify(Expr(opcode, regs[reg], operand), conditions)
     return conditions
 
 def modelnum(conditions, largest):