๐ Advent of Code 2'023 - Day 08
Day 08: Haunted Wasteland
* Cf. aoc. d. viii xxiii
Abridged Problem Description: Picture yourself lost in a haunted wasteland, with
only a map of cryptic instructions and a tangled network of nodes to guide you. Your
ultimate goal? To escape this spooky realm by reaching the node labeled ZZZ
, starting
from the ominous AAA
.
Parsing The Input
Iโve decided to use a map<string, pair<string, string>>
to store the graph. The key
is the nodeโs name, p.first
represents the left node and p.second
represents the
right node.
map<string, pair<string, string>> M;
To populate the map, we just need to parse the input. The input looks like this:
for (int i = 2; i < lines.size(); ++i) {
string key = lines[i].substr(0, 3);
M[key] = {lines[i].substr(7, 3), lines[i].substr(12, 3)};
}
Bene Nota: Iโm ignoring the first line because that is our instructions.
string instructions = lines[0];
PARS I
The first part of this challenge is straightforward โ we just need to keep following the
instructions until we reach ZZZ
. Itโs like being trapped in a labyrinth where you only
have one direction to go โ forward.
int64 ans = 0;
const string NEEDLE = "ZZZ";
string haystack = "AAA";
while (haystack != NEEDLE) {
for (const char &c: instructions) {
if (c == 'R') haystack = M[haystack].second;
else haystack = M[haystack].first;
ans++;
}
if (haystack == NEEDLE) break;
}
That was an easy star ๐
PARS II
Abridged Problem Description: Now, for the real challenge โ We should find the number of
steps required to make sure every node **A
ends up in the **Z
position simultaneously.
Part two is where things get spooky. As you might have guessed, the second part of the challenge is a bit more tricky. The same algorithm wonโt work here, because it would take too long to finish. We need to find a way to optimize it.
First, letโs make sure to find all nodes that follow the **A
pattern. We could do it while
weโre parsing the input. Iโve decided to store them in a vector<string> ans
.
string instructions = lines[0];
map<string, pair<string, string>> M;
vector<string> ans;
for (int i = 2; i < lines.size(); ++i) {
string key = lines[i].substr(0, 3);
if (key[2] == 'A') ans.push_back(key);
M[key] = {lines[i].substr(7, 3), lines[i].substr(12, 3)};
}
With that in place, we should calculate the cycles for each of these nodes.
* using int64 = long long
;
vector<int64> step_counts;
for (const auto &k: ans) {
string current = k;
while (true) {
for (const char &c: instructions) {
if (c == 'R') current = M[current].second;
else current = M[current].first;
steps++;
}
if (current.ends_with('Z')) {
step_counts.push_back(steps);
steps = 0;
break;
}
}
}
Now we just need to find the least common multiple of all these cycles. Iโve used the
gcd
function to help with the calculation.
int64 lcm = step_counts[0];
for (int i = 1; i < step_counts.size(); ++i) {
lcm = lcm * step_counts[i] / gcd(lcm, step_counts[i]);
}
return lcm;
Awesome! We solved the spooky puzzle! ๐๐
Click here to access the blogpost from @fefas