#include "aoc.h" #include 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; } struct message_queue { std::deque* qs; std::deque* qr; size_t c; }; typedef void (*f18)(size_t*, const char*, const char*, int64_t rs[26], message_queue& q); static void snd(size_t* i, const char* p1, const char* p2, int64_t rs[26], message_queue& q) { q.qs->push_back(get(*p1, rs)); q.c += 1; *i += 1; } static void rcv0(size_t* i, const char* p1, const char* p2, int64_t rs[26], message_queue& q) { 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], message_queue& q) { // if (!q.qr->empty()) { // auto x = q.qr->front(); // q.qr->pop_front(); // get(*p1, rs) = x; // *i += 1; // } // } static void set(size_t* i, const char* p1, const char* p2, int64_t rs[26], message_queue& qs) { 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], message_queue& q) { 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], message_queue& q) { 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], message_queue& q) { 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], message_queue& q) { 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& todos, int64_t rs[26], message_queue& q, 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, q); break; } } } return index; } static int64_t part1(const std::vector& todos) { size_t index{0}; int64_t rs[26] = {0}; std::deque q; message_queue mq = {&q, &q, 0}; while (index < todos.size()) { index = exec(index, todos, rs, mq, rcv0); } return q.back(); } // static void part2(const std::vector& 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 q0; // std::deque q1; // message_queue mq0 = {&q1, &q0, 0}; // message_queue mq1 = {&q0, &q1, 0}; // // while (i0 < todos.size() && i1 < todos.size()) { // i0 = exec(i0, todos, rs0, mq0, rcv1); // i1 = exec(i1, todos, rs1, mq1, rcv1); // printf("%zu %zu\n", mq0.c, mq1.c); // } // } std::pair day18(line_view file) { std::vector todos; per_line(file, [&todos](line_view lv) { todos.push_back(lv); return true; }); auto t0 = part1(todos); // part2(todos); return {t0, 0}; } } // namespace aoc2017