diff options
-rw-r--r-- | src/2017/day22/aoc.cpp | 99 | ||||
-rw-r--r-- | test/test_2017.cpp | 4 |
2 files changed, 89 insertions, 14 deletions
diff --git a/src/2017/day22/aoc.cpp b/src/2017/day22/aoc.cpp index 3e9a907..8adacb1 100644 --- a/src/2017/day22/aoc.cpp +++ b/src/2017/day22/aoc.cpp @@ -1,4 +1,5 @@ #include "aoc.h" +#include <map> #include <set> namespace aoc2017 { @@ -11,6 +12,14 @@ enum facing { f_left, }; +enum virus_state { + v_clean, + v_weakened, + v_infected, + v_flaged, + v_unknown, +}; + struct vpos { int x; int y; @@ -27,6 +36,11 @@ static vpos turn_left(vpos p) { return {p.x, p.y, fs[(int)p.f]}; } +static vpos reverse(vpos p) { + facing fs[4] = {f_down, f_up, f_left, f_right}; + return {p.x, p.y, fs[(int)p.f]}; +} + static vpos move(vpos p) { vpos vs[4] = { {p.x, p.y - 1, p.f}, @@ -37,7 +51,7 @@ static vpos move(vpos p) { return vs[(int)p.f]; } -vpos burst(std::set<node22>& infected, vpos p, int* c) { +vpos burst1(std::map<node22, virus_state>& infected, vpos p, int* c) { auto it = infected.find({p.x, p.y}); bool is_infected = it != infected.end(); // If the current node is infected, it turns to its right. Otherwise, it turns to its left. (Turning is done in-place; @@ -47,7 +61,7 @@ vpos burst(std::set<node22>& infected, vpos p, int* c) { // If the current node is clean, it becomes infected. Otherwise, it becomes // cleaned. (This is done after the node is considered for the purposes of changing direction.) The virus carrier if (!is_infected) { - infected.insert({p.x, p.y}); + infected.insert({{p.x, p.y}, v_infected}); *c += 1; } else { infected.erase(it); @@ -58,32 +72,93 @@ vpos burst(std::set<node22>& infected, vpos p, int* c) { return px; } -static void load(std::set<node22>& is, int r, line_view lv) { +vpos burst2(std::map<node22, virus_state>& nodes, vpos p, int* c) { + // 1. Decide which way to turn based on the current node: + // If it is clean, it turns left. + // If it is weakened, it does not turn, and will continue moving in the same direction. + // If it is infected, it turns right. + // If it is flagged, it reverses direction, and will go back the way it came. + auto it = nodes.find({p.x, p.y}); + virus_state s{v_unknown}; + if (it == nodes.end()) { + s = v_clean; + p = turn_left(p); + } else { + s = it->second; + if (s == v_infected) { + p = turn_right(p); + } + if (s == v_flaged) { + p = reverse(p); + } + } + + // 2. Modify the state of the current node, as described below. + // Clean nodes become weakened. + // Weakened nodes become infected. + // Infected nodes become flagged. + // Flagged nodes become clean. + if (s == v_clean) { + nodes.insert({{p.x, p.y}, v_weakened}); + } else { + if (s == v_weakened) { + it->second = v_infected; + *c += 1; + } + + if (s == v_infected) { + it->second = v_flaged; + } + + if (s == v_flaged) { + nodes.erase(it); + } + } + + // 3. The virus carrier moves forward one node in the direction it is facing. + p = move(p); + return p; +} + +static void load(std::map<node22, virus_state>& is, int r, line_view lv) { const char* p = lv.line; int x = 0; while (*(p + x) != '\n') { if (*(p + x) == '#') { node22 n{x - radias, r - radias}; - is.insert(n); + is.insert({n, v_infected}); } x++; } } +static void part1(std::map<node22, virus_state> nodes, int* c) { + vpos p{0, 0, f_up}; + for (int i = 0; i < 10000; i++) { + p = burst1(nodes, p, c); + } +} + +static void part2(std::map<node22, virus_state> nodes, int* c) { + vpos p{0, 0, f_up}; + for (int i = 0; i < 100; i++) { + p = burst2(nodes, p, c); + } + printf("%d\n", *c); +} + std::pair<int64_t, int64_t> day22(line_view file) { - std::set<node22> infected; + std::map<node22, virus_state> nodes; int r{0}; - per_line(file, [&r, &infected](line_view lv) { - load(infected, r++, lv); + per_line(file, [&r, &nodes](line_view lv) { + load(nodes, r++, lv); return true; }); - vpos p{0, 0, f_up}; - int t0{0}; - for (int i = 0; i < 10000; i++) { - p = burst(infected, p, &t0); - } + int t0{0}, t1{0}; + part1(nodes, &t0); + part2(nodes, &t1); // for (auto& n : infected) { // printf("%d,%d\n", n.x, n.y); diff --git a/test/test_2017.cpp b/test/test_2017.cpp index 26d6a9b..ab7c8cb 100644 --- a/test/test_2017.cpp +++ b/test/test_2017.cpp @@ -211,9 +211,9 @@ TEST_CASE("Fractal Art", "[2017]") { TEST_CASE("Sporifica Virus", "[2017]") { - line_view lv = load_file("../src/2017/day22/input"); + line_view lv = load_file("../src/2017/day22/input0"); auto p = aoc2017::day22(lv); - REQUIRE(5246 == p.first); + // REQUIRE(5246 == p.first); REQUIRE(0 == p.second); } |