#pragma once #include "common.h" namespace aoc2015 { struct Bit; template struct store; template struct store { int8_t pool[N * N] = {0}; void toggle(int x, int y) { pool[y * N + x] += 2; } void set(int x, int y) { pool[y * N + x] += 1; } void reset(int x, int y) { if (pool[y * N + x] > 0) { pool[y * N + x] -= 1; } } int count() const noexcept { int total{0}; for (auto i : pool) { total += i; } return total; } }; template struct store { constexpr static size_t size = N * N / 64 + 1; uint64_t pool[size] = {0}; void set(int x, int y) { uint64_t p = y * N + x; uint64_t r = p >> 6; uint64_t c = p & 63; uint64_t& byte = pool[r]; uint64_t mask = 1ll << c; byte |= mask; } void reset(int x, int y) { uint64_t p = y * N + x; uint64_t r = p >> 6; uint64_t c = p & 63; uint64_t& byte = pool[r]; uint64_t mask = ~(1ll << c); byte &= mask; } void toggle(int x, int y) { uint64_t p = y * N + x; uint64_t r = p >> 6; uint64_t c = p & 63; uint64_t& byte = pool[r]; uint64_t mask = 1ll << c; byte ^= mask; } int count() const noexcept { int total = 0; for (uint64_t i : pool) { total += __builtin_popcountll(i); } return total; } }; template struct grid { struct unit { int x; int y; }; store store_; template void traverse(unit u1, unit u2, F&& f, Args&&... args) { for (int i = u1.x; i <= u2.x; i++) { for (int j = u1.y; j <= u2.y; j++) { f(i, j, std::forward(args)...); } } } void turn_on(unit u1, unit u2) { traverse(u1, u2, [this](int i, int j) { store_.set(i, j); }); } void turn_off(unit u1, unit u2) { traverse(u1, u2, [this](int i, int j) { store_.reset(i, j); }); } void toggle(unit u1, unit u2) { traverse(u1, u2, [this](int i, int j) { store_.toggle(i, j); }); } std::pair parse(const char* p1, const char* p2) { unit u1; unit u2; int* is[] = {&u1.x, &u1.y, &u2.x, &u2.y}; int i = 0; const char* p = p1; while (i < 4 && p < p2) { int x = 0; while (*p >= '0' && *p <= '9') { x = x * 10 + *p - '0'; p++; } *is[i++] = x; while (*p < '0' || *p > '9') { p++; } } return {u1, u2}; } void parse(line_view lv) { static struct _ { void (grid::*action)(unit, unit); const char* key; } keywords[] = {{&grid::toggle, "toggle"}, {&grid::turn_off, "turn off"}, {&grid::turn_on, "turn on"}}; for (auto k : keywords) { if (lv.contains(k.key)) { const char* p1 = lv.line + strlen(k.key) + 1; const char* p2 = lv.line + lv.length; auto p = parse(p1, p2); (this->*k.action)(p.first, p.second); break; } } } }; std::pair day6(line_view); } // namespace aoc2015