aboutsummaryrefslogtreecommitdiff
path: root/src/2017/day22/aoc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/2017/day22/aoc.cpp')
-rw-r--r--src/2017/day22/aoc.cpp99
1 files changed, 87 insertions, 12 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);