#pragma once #include "common.h" #include namespace aoc2019 { struct belt { static constexpr int grid = 34; struct distance { int dx; int dy; }; struct pos { int x; int y; friend bool operator==(const pos &p1, const pos &p2) { return p1.x == p2.x && p1.y == p2.y; } }; char map[grid * grid] = {0}; belt(const belt& b) { memcpy(map, b.map, grid * grid); } belt& operator=(const belt& b) { if (this != &b) { memcpy(map, b.map, grid * grid); } return *this; } belt() {} char& get(int x, int y) { return map[y * grid + x]; } char& get(pos p) { return get(p.x, p.y); } void load(line_view lv, int row) { const char* p = lv.line; for (int i = 0; i < grid; i++) { get(i, row) = *(p + i); } } distance diff(pos px, pos p) const noexcept { auto d = distance{px.x - p.x, px.y - p.y}; int g = gcd(std::abs(d.dx), std::abs(d.dy)); return distance {d.dx / g, d.dy / g}; } distance dist(pos px, pos p) const noexcept { return distance{px.x - p.x, px.y - p.y}; } bool valid (pos p) const noexcept { return p.x >= 0 && p.x < grid && p.y >= 0 && p.y < grid; } pos next(pos p, distance d) const noexcept { return pos{p.x + d.dx, p.y + d.dy}; } bool blocked(pos p, pos m) { auto d = diff(p, m); auto n = next(m, d); while (valid(n) && !(n == p)) { if (get(n) == '#') { return true; } n = next(n, d); } return false; } template void iterate(F&& f, Args&&... args) { for(int y = 0; y < grid; y++) { for (int x = 0; x < grid; x++) { f(pos{x, y}, std::forward(args)...); } } } void print() { iterate([this](pos p){ printf("%c", get(p)); if (p.x == grid - 1) { printf("\n"); } }); printf("\n"); } void count(pos m, int* c) { iterate([this, &m, &c](pos p){ if (get(p) == '#' && !(p == m)) { if (!blocked(p, m)) { *c += 1; } } }); } }; std::pair day10(line_view); }