aboutsummaryrefslogtreecommitdiff
path: root/src/2017/day18/aoc.cpp
blob: 9cef4c9e6548c41c8cad7aff0447339571b2e2c4 (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "aoc.h"
#include <deque>

namespace aoc2017 {
static int64_t& get(char x, int64_t rs[26]) { return rs[x - 'a']; }
static void get_number(const char** pp, int64_t* d) {
  const char* p = *pp;
  int sign = 1;
  if (*p == '-') {
    sign = -1;
    p++;
  }
  while (*p >= '0' && *p <= '9') {
    *d = *d * 10 + *p - '0';
    p++;
  }
  *d *= sign;
  *pp = p;
}

static int64_t get_number(const char* p, int64_t rs[26]) {
  int64_t d{0};
  if (*p == '-' || (*p >= '0' && (*p <= '9'))) {
    get_number(&p, &d);
  } else {
    d = get(*p, rs);
  }
  return d;
}

typedef void (*f18)(size_t*, const char*, const char*, int64_t rs[26], std::deque<int64_t>* qs[2]);

static void snd(size_t* i, const char* p1, const char* p2, int64_t rs[26], std::deque<int64_t>* qs[2]) {
  qs[0]->push_back(get(*p1, rs));
  *i += 1;
}

static void rcv0(size_t* i, const char* p1, const char* p2, int64_t rs[26], std::deque<int64_t>* qs[2]) {
  auto d = get_number(p1, rs);
  if (d != 0) {
    // printf("%ld\n", sounds.back());
    *i = INT64_MAX - 1;
  }
  *i += 1;
}

static void rcv1(size_t* i, const char* p1, const char* p2, int64_t rs[26], std::deque<int64_t>* qs[2]) {
  if (!qs[1]->empty()) {
    auto x = qs[1]->front();
    qs[1]->pop_front();
    get(*p1, rs) = x;
    *i += 1;
  }
}

static void set(size_t* i, const char* p1, const char* p2, int64_t rs[26], std::deque<int64_t>* qs[2]) {
  get(*p1, rs) = get_number(p2, rs);
  *i += 1;
}

static void add(size_t* i, const char* p1, const char* p2, int64_t rs[26], std::deque<int64_t>* qs[2]) {
  get(*p1, rs) += get_number(p2, rs);
  *i += 1;
}

static void mul(size_t* i, const char* p1, const char* p2, int64_t rs[26], std::deque<int64_t>* qs[2]) {
  get(*p1, rs) *= get_number(p2, rs);
  *i += 1;
}

static void mod(size_t* i, const char* p1, const char* p2, int64_t rs[26], std::deque<int64_t>* qs[2]) {
  get(*p1, rs) %= get_number(p2, rs);
  *i += 1;
}

static void jgz(size_t* i, const char* p1, const char* p2, int64_t rs[26], std::deque<int64_t>* qs[2]) {
  auto d0 = get_number(p1, rs);
  auto d1 = get_number(p2, rs);
  *i += d0 > 0 ? d1 : 1;
}

// static void print() {
//   char as[] = {'i', 'a', 'p', 'f', 'b'};
//   for (auto& a: as) {
//     printf("[%c: %ld] ", a, get(a));
//   }
//   printf("\n");
// }

static size_t exec(size_t index, const std::vector<line_view>& todos, int64_t rs[26], std::deque<int64_t>* qs[2],
                   f18 rcv) {
  if (index < todos.size()) {
    f18 fs[] = {snd, set, add, mul, mod, jgz, rcv};
    const char* cs[] = {"snd", "set", "add", "mul", "mod", "jgz", "rcv"};
    auto& todo = todos[index];
    const char* p = todo.line;
    auto match = [](const char* p, const char* p0) -> bool {
      for (int i = 0; i < 3; i++) {
        if (*(p + i) != *(p0 + i)) {
          return false;
        }
      }
      return true;
    };

    for (size_t i = 0; i < 7; i++) {
      if (match(p, cs[i])) {
        fs[i](&index, p + 4, p + 6, rs, qs);
        break;
      }
    }
  }
  return index;
}

static int64_t part1(const std::vector<line_view>& todos) {
  size_t index{0};
  int64_t rs[26] = {0};
  std::deque<int64_t> q;
  std::deque<int64_t>* qs[2] = {&q, &q};

  while (index < todos.size()) {
    index = exec(index, todos, rs, qs, rcv0);
  }
  return q.back();
}

static void part2(const std::vector<line_view>& todos) {
  size_t i0{0};
  size_t i1{0};

  int64_t rs0[26] = {0};
  get('p', rs0) = 0;
  int64_t rs1[26] = {0};
  get('p', rs1) = 1;

  std::deque<int64_t> q0;
  std::deque<int64_t> q1;
  std::deque<int64_t>* qs0[2] = {&q1, &q0};
  std::deque<int64_t>* qs1[2] = {&q0, &q1};

  while (i0 < todos.size() && i1 < todos.size()) {
    i0 = exec(i0, todos, rs0, qs0, rcv1);
    i1 = exec(i1, todos, rs1, qs1, rcv1);
  }
}

std::pair<int64_t, int64_t> day18(line_view file) {
  std::vector<line_view> todos;
  per_line(file, [&todos](line_view lv) {
    todos.push_back(lv);
    return true;
  });

  auto t0 = part1(todos);
  return {t0, 0};
}
} // namespace aoc2017