diff --git a/2019/24.cpp b/2019/24.cpp index aac02d9..9b9abb9 100644 --- a/2019/24.cpp +++ b/2019/24.cpp @@ -1,19 +1,14 @@ #include +#include #include #include -#include -#include #include -#include -#include +#include #include +#include #include #include -#include -#include -#include -#include -#include +#include #include #include @@ -39,7 +34,7 @@ struct Map { }; auto FindBugs(Map const& map) { - std::set result; + std::vector result; std::int64_t w = map.rows[0].size(); std::int64_t h = map.rows.size(); @@ -47,92 +42,72 @@ auto FindBugs(Map const& map) { for (std::int64_t x = 0; x < w; x++) { for (std::int64_t y = 0; y < h; y++) { Coord const c = {x,y}; - if (map[c] == '#') result.insert(c); + if (map[c] == '#') result.push_back(c); } } return result; } -auto Neighbor1(Coord c) { - std::vector result; - result.reserve(4); - if (c.x > 0) result.push_back(Left(c)); - if (c.x < 4) result.push_back(Right(c)); - if (c.y > 0) result.push_back(Up(c)); - if (c.y < 4) result.push_back(Down(c)); - return result; -} - -auto Neighbor2(std::pair cd) { - auto [c,d] = cd; - std::vector> result; - result.reserve(8); - - if (c.x == 3 && c.y == 2) { - for (std::int64_t yi = 0; yi < 5; yi++) { - result.push_back({{4,yi},d+1}); - } - } else if (c.x > 0) { - result.push_back({Left(c),d}); - } else { - result.push_back({{1,2},d-1}); +struct Neighbor1 { + auto operator()(Coord c, auto f) const -> void { + if (c.x > 0) f(Left(c)); + if (c.x < 4) f(Right(c)); + if (c.y > 0) f(Up(c)); + if (c.y < 4) f(Down(c)); } +}; - if (c.x == 1 && c.y == 2) { - for (std::int64_t yi = 0; yi < 5; yi++) { - result.push_back({{0,yi},d+1}); - } - } else if (c.x < 4) { - result.push_back({Right(c),d}); - } else { - result.push_back({{3,2},d-1}); +struct Neighbor2 { + using C3 = std::pair; + auto operator()(C3 cd, auto f) const -> void { + auto const [c,d] = cd; + + auto left_neighbors = [&f](Coord c, std::int64_t d, auto k_, auto k) { + c = k_(c); + if (c.x == 1 && c.y == 0) { + for (std::int64_t yi = -2; yi <= 2; yi++) { + f({k({2,yi}),d+1}); + } + } else if (c.x > -2) { + f({k(Left(c)),d}); + } else { + f({k({-1,0}),d-1}); + } + }; + auto id = [](Coord i) { return i; }; + left_neighbors(c, d, id, id); + left_neighbors(c, d, Turn180, Turn180); + left_neighbors(c, d, CW, CCW); + left_neighbors(c, d, CCW, CW); } +}; - if (c.x == 2 && c.y == 3) { - for (std::int64_t xi = 0; xi < 5; xi++) { - result.push_back({{xi,4},d+1}); - } - } else if (c.y > 0) { - result.push_back({Up(c),d}); - } else { - result.push_back({{2,1},d-1}); - } - - if (c.x == 2 && c.y == 1) { - for (std::int64_t xi = 0; xi < 5; xi++) { - result.push_back({{xi,0},d+1}); - } - } else if (c.y < 4) { - result.push_back({Down(c),d}); - } else { - result.push_back({{2,3},d-1}); - } - - return result; -} - -template -auto Step(std::set const& bugs, F neighbors) +template +auto Step(std::vector const& bugs, F with_neighbors = F{}) { std::map adjacent; for (auto const& x : bugs) { - for (auto const& n : neighbors(x)) { - adjacent[n]++; - } + with_neighbors(x, [&adjacent](C n) -> void { adjacent[n]++; }); } - std::set result; + std::vector result; for (auto const& [k,v] : adjacent) { switch (v) { - case 1: result.insert(k); break; - case 2: if (!bugs.contains(k)) result.insert(k); break; + case 1: + result.push_back(k); + break; + case 2: + if (!std::binary_search(bugs.begin(), bugs.end(), k)) { + result.push_back(k); + break; + } } } return result; } -auto Bio(std::set const& bugs) -> std::uint32_t { +auto Bio(std::vector const& bugs) -> std::uint32_t { std::uint32_t result = 0; for (auto const& c : bugs) { result |= 1U << (5 * c.y + c.x); @@ -140,23 +115,23 @@ auto Bio(std::set const& bugs) -> std::uint32_t { return result; } -auto Part1(std::set const& bugs) -> std::uint32_t { +auto Part1(std::vector const& bugs) -> std::uint32_t { auto cursor = bugs; std::set seen; std::uint32_t bio; while (seen.insert(bio = Bio(cursor)).second) { - cursor = Step(cursor, Neighbor1); + cursor = Step(cursor); } return bio; } -auto Part2(std::set const& bugs) { - std::set> bugs2; - for (auto const& x : bugs) { - bugs2.insert({x,0}); +auto Part2(std::vector const& bugs) { + std::vector> bugs2; + for (auto const& [x,y] : bugs) { + bugs2.push_back({{x-2,y-2},0}); } for (int i = 0; i < 200; i++) { - bugs2 = Step(bugs2, Neighbor2); + bugs2 = Step(bugs2); } return bugs2.size(); } diff --git a/lib/include/aocpp/Coord.hpp b/lib/include/aocpp/Coord.hpp index e9c8ab5..81ddef8 100644 --- a/lib/include/aocpp/Coord.hpp +++ b/lib/include/aocpp/Coord.hpp @@ -40,6 +40,8 @@ auto CW(Coord) -> Coord; /// Rotate counter-clockwise auto CCW(Coord) -> Coord; +auto Turn180(Coord) -> Coord; + auto Norm1(Coord) -> std::int64_t; /// Add two coordinates pairwise diff --git a/lib/src/Coord.cpp b/lib/src/Coord.cpp index e749f08..7800f5b 100644 --- a/lib/src/Coord.cpp +++ b/lib/src/Coord.cpp @@ -62,9 +62,11 @@ auto CW(Coord c) -> Coord { } auto CCW(Coord c) -> Coord { - c = Invert(c); - c.y = -c.y; - return c; + return CW(CW(CW(c))); +} + +auto Turn180(Coord c) -> Coord { + return CW(CW(c)); } auto Norm1(Coord c) -> std::int64_t {