aboutsummaryrefslogtreecommitdiff
path: root/src/2022/day21/aoc.cpp
blob: f37368964b89da2269f1d3b1ad46b885b42b763e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include "aoc.h"
#include <functional>
#include <map>
#include <set>

namespace aoc2022 {

std::map<line_view, monkey_math> monkeys;

struct monkey_tree {
  monkey_math* name;
  monkey_tree* left = nullptr;
  monkey_tree* right = nullptr;

  monkey_tree(monkey_math* n) : name(n) {}
};

void find(monkey_tree* t, line_view name, monkey_tree** m, std::set<monkey_math*>& ms) {
  if (*m == nullptr && t->left)
    find(t->left, name, m, ms);
  if (*m == nullptr && t->right)
    find(t->right, name, m, ms);

  if (t->name->op[0] == name) {
    *m = t;
    ms.insert(t->name);
  }
  if (*m != nullptr) {
    if (t->left == *m)
      ms.insert(t->name);
    if (t->right == *m)
      ms.insert(t->name);
    *m = t;
  }
}

int64_t get_value(line_view name, monkey_tree* t) {
  auto& m = monkeys[name];
  if (m.value == INT64_MAX) {
    t->left = new monkey_tree{&monkeys[m.op[1]]};
    t->right = new monkey_tree{&monkeys[m.op[2]]};

    int64_t v1 = get_value(m.op[1], t->left);
    int64_t v2 = get_value(m.op[2], t->right);
    std::function<int64_t(int64_t, int64_t)> fs[] = {
        [](int64_t x1, int64_t x2) { return x1 + x2; },
        [](int64_t x1, int64_t x2) { return x1 - x2; },
        [](int64_t x1, int64_t x2) { return x1 * x2; },
        [](int64_t x1, int64_t x2) { return x1 / x2; },
    };
    m.value = fs[(int)m.todo](v1, v2);
  }
  return m.value;
}

int64_t get_value(int64_t value, const std::set<monkey_math*>& ms, monkey_tree* t) {
  // std::cout << t->name->op[0] << " needs to be " << value << std::endl;
  if (t->name->op[0] == "humn") {
    return value;
  } else {
    bool b = ms.find(t->left->name) == ms.end();
    int64_t v0 = b ? monkeys[t->left->name->op[0]].value : monkeys[t->right->name->op[0]].value;
    monkey_tree* t0 = b ? t->right : t->left;
    switch (t->name->todo) {
    case oper::add:
      return get_value(value - v0, ms, t0);
    case oper::minus:
      return get_value(b ? v0 - value : value + v0, ms, t0);
    case oper::multiply:
      return get_value(value / v0, ms, t0);
    case oper::division:
      return get_value(b ? v0 / value : value * v0, ms, t0);
    case none: break;
    }
  }
  return 0;
}

std::pair<int64_t, int64_t> day21(line_view file) {
  per_line(file, [](line_view lv) {
    auto m = monkey_math{lv};
    // m.print();
    monkeys.insert({m.op[0], m});
    return true;
  });
  auto& m = monkeys["root"];
  monkey_tree tree{&m};
  int64_t n1 = get_value("root", &tree);

  monkey_tree* target = nullptr;
  std::set<monkey_math*> ms;
  find(&tree, "humn", &target, ms);

  auto n2 = get_value(monkeys["qwqj"].value, ms, tree.left);
  // auto n2 = get_value(monkeys["sjmn"].value, ms, tree.left);
  return {n1, n2};
}
} // namespace aoc2022