24_alu.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #!/usr/bin/env python3
  2. import sys
  3. from operator import add, mul, floordiv, mod, eq
  4. OPS = {'add': add, 'mul': mul, 'div': floordiv, 'mod': mod, 'eql': eq}
  5. class Expr:
  6. def __init__(self, opcode, left, right):
  7. self.opcode = opcode
  8. self.left = left
  9. self.right = right
  10. def reduce(self, conditions):
  11. lconst = isinstance(self.left, int)
  12. rconst = isinstance(self.right, int)
  13. if lconst and rconst:
  14. return int(OPS[self.opcode](self.left, self.right))
  15. elif lconst and self.opcode in ('add', 'mul', 'eql'):
  16. return Expr(self.opcode, self.right, self.left).reduce(conditions)
  17. if self.opcode == 'add':
  18. if self.right == 0:
  19. return self.left
  20. if self.left.opcode == 'add':
  21. right = self.left.right + self.right
  22. return Expr('add', self.left.left, right)
  23. elif self.opcode == 'mul':
  24. if self.right == 0:
  25. return 0
  26. if self.right == 1:
  27. return self.left
  28. elif self.opcode == 'eql':
  29. offset = self.left.right
  30. if rconst or offset > 9:
  31. return 0
  32. conditions.append((self.left.left.left, self.right.left, offset))
  33. return 1
  34. elif self.opcode == 'div':
  35. return self.left if self.right == 1 else self.left.left.left
  36. elif self.opcode == 'mod':
  37. if self.left.left.opcode == 'inp':
  38. return self.left
  39. return self.left.right
  40. return self
  41. def parse(line):
  42. parts = line.split()
  43. if len(parts) == 2:
  44. operand = None
  45. elif parts[2].isdigit() or parts[2].startswith('-'):
  46. operand = int(parts[2])
  47. else:
  48. operand = parts[2]
  49. return parts[0], parts[1], operand
  50. def input_conditions(program):
  51. conditions = []
  52. regs = {'w': 0, 'x': 0, 'y': 0, 'z': 0}
  53. index = 0
  54. for opcode, reg, operand in program:
  55. if opcode == 'inp':
  56. regs[reg] = Expr('inp', index, None)
  57. index += 1
  58. else:
  59. if not isinstance(operand, int):
  60. operand = regs[operand]
  61. regs[reg] = Expr(opcode, regs[reg], operand).reduce(conditions)
  62. return conditions
  63. def modelnum(conditions, largest):
  64. nr = [0] * 14
  65. for a, b, offset in conditions:
  66. nr[a] = 9 - max(offset, 0) if largest else 1 - min(offset, 0)
  67. nr[b] = nr[a] + offset
  68. return ''.join(map(str, nr))
  69. conditions = input_conditions(map(parse, sys.stdin))
  70. print(modelnum(conditions, True))
  71. print(modelnum(conditions, False))