24_alu.py 2.2 KB

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