21.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. from queue import deque
  2. lines = [line.strip().split(": ") for line in open("21.input")]
  3. def part1():
  4. known = {p[0]: int(p[1]) for p in lines if p[1].isdecimal()}
  5. unknown = deque([(p[0], p[1]) for p in lines if not p[1].isdecimal()])
  6. while "root" not in known:
  7. name, exp = unknown.popleft()
  8. left, op, right = exp.split(" ")
  9. if left in known and right in known:
  10. known[name] = eval(f"known[\"{left}\"] {op} known[\"{right}\"]")
  11. else:
  12. unknown.append((name, exp))
  13. print("Part 1:", int(known["root"]))
  14. monkeys = {p[0]: p[1] for p in lines}
  15. def simplify(name):
  16. exp = monkeys[name]
  17. if name == "humn":
  18. return "x"
  19. if exp.isdecimal():
  20. return int(exp)
  21. left, op, right = exp.split(" ")
  22. left, right = simplify(left), simplify(right)
  23. if isinstance(left, int) and isinstance(right, int):
  24. return int(eval(f"left {op} right"))
  25. if left == "x" or right == "x":
  26. return (left, op, right)
  27. return (left, op, right)
  28. def solver(lhs, rhs):
  29. while lhs != "x":
  30. left, op, right = lhs
  31. if op == "+":
  32. if isinstance(left, int):
  33. rhs -= left
  34. lhs = right
  35. continue
  36. elif isinstance(right, int):
  37. rhs -= right
  38. lhs = left
  39. continue
  40. if op == "-":
  41. if isinstance(left, int):
  42. rhs = -rhs
  43. rhs += left
  44. lhs = right
  45. continue
  46. elif isinstance(right, int):
  47. rhs += right
  48. lhs = left
  49. continue
  50. if op == "/":
  51. if isinstance(left, int):
  52. raise ValueError("Cannot solve with x in denominator")
  53. elif isinstance(right, int):
  54. rhs *= right
  55. lhs = left
  56. continue
  57. if op == "*":
  58. if isinstance(left, int):
  59. rhs /= left
  60. lhs = right
  61. continue
  62. elif isinstance(right, int):
  63. rhs /= right
  64. lhs = left
  65. continue
  66. return rhs
  67. def part2():
  68. left, right = monkeys["root"].split(" + ")
  69. print("Part 2:", int(solver(simplify(left), simplify(right))))
  70. part1()
  71. part2()