24
This commit is contained in:
parent
3d665e5ebb
commit
4a8b31bd86
173
2019/24.cpp
Normal file
173
2019/24.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <bitset>
|
||||
#include <deque>
|
||||
#include <cctype>
|
||||
#include <queue>
|
||||
#include <map>
|
||||
|
||||
#include <aocpp/Startup.hpp>
|
||||
#include <aocpp/Coord.hpp>
|
||||
|
||||
using namespace aocpp;
|
||||
|
||||
namespace {
|
||||
|
||||
Coord(* const directions[4])(Coord) = {Up, Down, Left, Right};
|
||||
|
||||
struct Map {
|
||||
std::vector<std::string> rows;
|
||||
|
||||
auto operator[](Coord c) -> char& { return rows[c.y][c.x]; }
|
||||
auto operator[](Coord c) const -> char { return rows[c.y][c.x]; }
|
||||
|
||||
static auto Parse(std::istream & in) -> Map {
|
||||
Map result;
|
||||
std::string line;
|
||||
while (std::getline(in, line)) {
|
||||
result.rows.emplace_back(std::move(line));
|
||||
}
|
||||
return {result};
|
||||
}
|
||||
};
|
||||
|
||||
auto FindBugs(Map const& map) {
|
||||
std::set<Coord> result;
|
||||
|
||||
std::int64_t w = map.rows[0].size();
|
||||
std::int64_t h = map.rows.size();
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
auto Neighbor1(Coord c) {
|
||||
std::vector<Coord> result;
|
||||
result.reserve(4);
|
||||
if (c.x > 0) result.push_back({c.x-1,c.y});
|
||||
if (c.x < 4) result.push_back({c.x+1,c.y});
|
||||
if (c.y > 0) result.push_back({c.x,c.y-1});
|
||||
if (c.y < 4) result.push_back({c.x,c.y+1});
|
||||
return result;
|
||||
}
|
||||
|
||||
auto Neighbor2(std::pair<Coord, std::int64_t> cd) {
|
||||
auto [c,d] = cd;
|
||||
std::vector<std::pair<Coord, std::int64_t>> 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({{c.x-1,c.y},d});
|
||||
} else {
|
||||
result.push_back({{1,2},d-1});
|
||||
}
|
||||
|
||||
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({{c.x+1,c.y},d});
|
||||
} else {
|
||||
result.push_back({{3,2},d-1});
|
||||
}
|
||||
|
||||
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({{c.x,c.y-1},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({{c.x,c.y+1},d});
|
||||
} else {
|
||||
result.push_back({{2,3},d-1});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class F, class C>
|
||||
auto Step(std::set<C> const& bugs, F const& neighbors)
|
||||
{
|
||||
std::map<C, int> adjacent;
|
||||
for (auto const& x : bugs) {
|
||||
for (auto const& n : neighbors(x)) {
|
||||
adjacent[n]++;
|
||||
}
|
||||
}
|
||||
|
||||
std::set<C> 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;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
auto Bio(std::set<Coord> const& bugs) {
|
||||
std::uint32_t result = 0;
|
||||
for (auto const& c : bugs) {
|
||||
result |= 1U << (5 * c.y + c.x);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
auto Part1(std::set<Coord> const& bugs) {
|
||||
std::int64_t n = 0;
|
||||
auto cursor = bugs;
|
||||
std::set<std::uint32_t> seen;
|
||||
while (seen.insert(Bio(cursor)).second) {
|
||||
n++;
|
||||
cursor = Step(cursor, Neighbor1);
|
||||
}
|
||||
return Bio(cursor);
|
||||
}
|
||||
|
||||
auto Part2(std::set<Coord> const& bugs) {
|
||||
std::set<std::pair<Coord,std::int64_t>> bugs2;
|
||||
for (auto const& x : bugs) {
|
||||
bugs2.insert({x,0});
|
||||
}
|
||||
for (int i = 0; i < 200; i++) {
|
||||
bugs2 = Step(bugs2, Neighbor2);
|
||||
}
|
||||
return bugs2.size();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
auto main(int argc, char** argv) -> int {
|
||||
auto const bugs = FindBugs(Map::Parse(Startup(argc, argv)));
|
||||
std::cout << "Part 1: " << Part1(bugs) << std::endl;
|
||||
std::cout << "Part 2: " << Part2(std::move(bugs)) << std::endl;
|
||||
}
|
@ -48,3 +48,6 @@ target_link_libraries(20 aocpp)
|
||||
|
||||
add_executable(23 23.cpp)
|
||||
target_link_libraries(23 aocpp intcode)
|
||||
|
||||
add_executable(24 24.cpp)
|
||||
target_link_libraries(24 aocpp)
|
||||
|
Loading…
Reference in New Issue
Block a user