aboutsummaryrefslogtreecommitdiff
path: root/src/2016
diff options
context:
space:
mode:
authorkaiwu <kaiwu2004@gmail.com>2023-01-25 17:31:10 +0800
committerkaiwu <kaiwu2004@gmail.com>2023-01-25 17:31:10 +0800
commit5d5bb7cd4faf03b34407a9e26ca76aac802a7306 (patch)
treea7a91a22fee93d64a3528f2be2713b26995ee4ec /src/2016
parent2be2127f7d5ec7796f4e5b5a69068db4c1ccc42b (diff)
downloadadvent-of-code-5d5bb7cd4faf03b34407a9e26ca76aac802a7306.tar.gz
advent-of-code-5d5bb7cd4faf03b34407a9e26ca76aac802a7306.zip
2016 day17
Diffstat (limited to 'src/2016')
-rw-r--r--src/2016/day17/README.md50
-rw-r--r--src/2016/day17/aoc.cpp97
-rw-r--r--src/2016/day17/aoc.h2
-rw-r--r--src/2016/day18/README.md52
-rw-r--r--src/2016/day18/input1
-rw-r--r--src/2016/day18/input010
6 files changed, 210 insertions, 2 deletions
diff --git a/src/2016/day17/README.md b/src/2016/day17/README.md
index e69de29..fd5aa4b 100644
--- a/src/2016/day17/README.md
+++ b/src/2016/day17/README.md
@@ -0,0 +1,50 @@
+--- Day 17: Two Steps Forward ---
+
+You're trying to access a secure vault protected by a 4x4 grid of small rooms connected by doors. You start in the top-left room (marked S), and you can access the vault (marked V) once you reach the bottom-right room:
+
+#########
+#S| | | #
+#-#-#-#-#
+# | | | #
+#-#-#-#-#
+# | | | #
+#-#-#-#-#
+# | | |
+####### V
+
+Fixed walls are marked with #, and doors are marked with - or |.
+
+The doors in your current room are either open or closed (and locked) based on the hexadecimal MD5 hash of a passcode (your puzzle input) followed by a sequence of uppercase characters representing the path you have taken so far (U for up, D for down, L for left, and R for right).
+
+Only the first four characters of the hash are used; they represent, respectively, the doors up, down, left, and right from your current position. Any b, c, d, e, or f means that the corresponding door is open; any other character (any number or a) means that the corresponding door is closed and locked.
+
+To access the vault, all you need to do is reach the bottom-right room; reaching this room opens the vault and all doors in the maze.
+
+For example, suppose the passcode is hijkl. Initially, you have taken no steps, and so your path is empty: you simply find the MD5 hash of hijkl alone. The first four characters of this hash are ced9, which indicate that up is open (c), down is open (e), left is open (d), and right is closed and locked (9). Because you start in the top-left corner, there are no "up" or "left" doors to be open, so your only choice is down.
+
+Next, having gone only one step (down, or D), you find the hash of hijklD. This produces f2bc, which indicates that you can go back up, left (but that's a wall), or right. Going right means hashing hijklDR to get 5745 - all doors closed and locked. However, going up instead is worthwhile: even though it returns you to the room you started in, your path would then be DU, opening a different set of doors.
+
+After going DU (and then hashing hijklDU to get 528e), only the right door is open; after going DUR, all doors lock. (Fortunately, your actual passcode is not hijkl).
+
+Passcodes actually used by Easter Bunny Vault Security do allow access to the vault if you know the right path. For example:
+
+ If your passcode were ihgpwlah, the shortest path would be DDRRRD.
+ With kglvqrro, the shortest path would be DDUDRLRRUDRD.
+ With ulqzkmiv, the shortest would be DRURDRUDDLLDLUURRDULRLDUUDDDRR.
+
+Given your vault's passcode, what is the shortest path (the actual path, not just the length) to reach the vault?
+
+Your puzzle input is bwnlcvfs.
+
+--- Part Two ---
+
+You're curious how robust this security solution really is, and so you decide to find longer and longer paths which still provide access to the vault. You remember that paths always end the first time they reach the bottom-right room (that is, they can never pass through it, only end in it).
+
+For example:
+
+ If your passcode were ihgpwlah, the longest path would take 370 steps.
+ With kglvqrro, the longest path would be 492 steps long.
+ With ulqzkmiv, the longest path would be 830 steps long.
+
+What is the length of the longest path that reaches the vault?
+
diff --git a/src/2016/day17/aoc.cpp b/src/2016/day17/aoc.cpp
index 8696528..dee844c 100644
--- a/src/2016/day17/aoc.cpp
+++ b/src/2016/day17/aoc.cpp
@@ -1,6 +1,101 @@
#include "aoc.h"
+#include "md5.h"
+#include <deque>
+#include <map>
+#include <set>
namespace aoc2016 {
-std::pair<int64_t, int64_t> day17(line_view) { return {0, 0}; }
+struct pos {
+ int x;
+ int y;
+ int n;
+ std::string* path;
+
+ bool operator==(pos p) { return x == p.x && y == p.y; }
+ friend bool operator<(pos p1, pos p2) { return p1.x < p2.x ? true : p1.x > p2.x ? false : p1.y < p2.y; }
+ bool isvalid() const noexcept { return x > 0 && x < 5 && y > 0 && y < 5; }
+};
+
+static pos bfs(pos p, pos target, const std::string& passcode) {
+ std::deque<pos> q;
+ // std::set<pos> visited;
+ q.push_back(p);
+
+ auto is_open = [](char c) { return c > 'a' && c <= 'f'; };
+ while (!q.empty()) {
+ auto s = q.size();
+ while (s-- > 0) {
+ pos p0 = q.front();
+ q.pop_front();
+ if (p0 == target) {
+ return p0;
+ }
+
+ pos ns[4] = {
+ {p0.x, p0.y - 1, p0.n + 1, new std::string(*p0.path)},
+ {p0.x, p0.y + 1, p0.n + 1, new std::string(*p0.path)},
+ {p0.x - 1, p0.y, p0.n + 1, new std::string(*p0.path)},
+ {p0.x + 1, p0.y, p0.n + 1, new std::string(*p0.path)},
+ };
+
+ for (size_t i = 0; i < 4; i++) {
+ pos nx = ns[i];
+ std::string pass{passcode};
+ pass.append(*nx.path);
+ char md5[33] = {0};
+ memcpy(md5, md5sum((char*)pass.c_str()), 32);
+ // printf("%s: %d %d %d %s\n", md5, p0.x, p0.y, p0.n, (*p0.path).c_str());
+ if (nx.isvalid() && is_open(*(md5 + i))) {
+ char direction[] = {'U', 'D', 'L', 'R'};
+ nx.path->push_back(direction[i]);
+ q.push_back(nx);
+ }
+ }
+ }
+ }
+
+ return target;
+}
+
+static void dfs(pos p0, pos target, const std::string& passcode, int* max) {
+ if (p0 == target) {
+ if (*max < p0.n) {
+ *max = p0.n;
+ }
+ } else {
+ pos ns[4] = {
+ {p0.x, p0.y - 1, p0.n + 1, new std::string(*p0.path)},
+ {p0.x, p0.y + 1, p0.n + 1, new std::string(*p0.path)},
+ {p0.x - 1, p0.y, p0.n + 1, new std::string(*p0.path)},
+ {p0.x + 1, p0.y, p0.n + 1, new std::string(*p0.path)},
+ };
+
+ auto is_open = [](char c) { return c > 'a' && c <= 'f'; };
+ for (size_t i = 0; i < 4; i++) {
+ pos nx = ns[i];
+ std::string pass{passcode};
+ pass.append(*nx.path);
+ char md5[33] = {0};
+ memcpy(md5, md5sum((char*)pass.c_str()), 32);
+ if (nx.isvalid() && is_open(*(md5 + i))) {
+ char direction[] = {'U', 'D', 'L', 'R'};
+ nx.path->push_back(direction[i]);
+ dfs(nx, target, passcode, max);
+ }
+ }
+ }
+}
+
+std::pair<std::string, int64_t> day17(line_view) {
+ static std::string ss[] = {"", "UNKNOWN"};
+ pos b = {1, 1, 0, ss};
+ pos e = {4, 4, INT32_MAX, ss + 1};
+
+ auto p = bfs(b, e, "bwnlcvfs");
+ int max{INT32_MIN};
+ dfs(b, e, "bwnlcvfs", &max);
+
+ return {*p.path, max};
+}
} // namespace aoc2016
diff --git a/src/2016/day17/aoc.h b/src/2016/day17/aoc.h
index 5cde607..8b629da 100644
--- a/src/2016/day17/aoc.h
+++ b/src/2016/day17/aoc.h
@@ -3,5 +3,5 @@
#include <vector>
namespace aoc2016 {
-std::pair<int64_t, int64_t> day17(line_view);
+std::pair<std::string, int64_t> day17(line_view);
}
diff --git a/src/2016/day18/README.md b/src/2016/day18/README.md
index e69de29..f9a0ec6 100644
--- a/src/2016/day18/README.md
+++ b/src/2016/day18/README.md
@@ -0,0 +1,52 @@
+--- Day 18: Like a Rogue ---
+
+As you enter this room, you hear a loud click! Some of the tiles in the floor here seem to be pressure plates for traps, and the trap you just triggered has run out of... whatever it tried to do to you. You doubt you'll be so lucky next time.
+
+Upon closer examination, the traps and safe tiles in this room seem to follow a pattern. The tiles are arranged into rows that are all the same width; you take note of the safe tiles (.) and traps (^) in the first row (your puzzle input).
+
+The type of tile (trapped or safe) in each row is based on the types of the tiles in the same position, and to either side of that position, in the previous row. (If either side is off either end of the row, it counts as "safe" because there isn't a trap embedded in the wall.)
+
+For example, suppose you know the first row (with tiles marked by letters) and want to determine the next row (with tiles marked by numbers):
+
+ABCDE
+12345
+
+The type of tile 2 is based on the types of tiles A, B, and C; the type of tile 5 is based on tiles D, E, and an imaginary "safe" tile. Let's call these three tiles from the previous row the left, center, and right tiles, respectively. Then, a new tile is a trap only in one of the following situations:
+
+ Its left and center tiles are traps, but its right tile is not.
+ Its center and right tiles are traps, but its left tile is not.
+ Only its left tile is a trap.
+ Only its right tile is a trap.
+
+In any other situation, the new tile is safe.
+
+Then, starting with the row ..^^., you can determine the next row by applying those rules to each new tile:
+
+ The leftmost character on the next row considers the left (nonexistent, so we assume "safe"), center (the first ., which means "safe"), and right (the second ., also "safe") tiles on the previous row. Because all of the trap rules require a trap in at least one of the previous three tiles, the first tile on this new row is also safe, ..
+ The second character on the next row considers its left (.), center (.), and right (^) tiles from the previous row. This matches the fourth rule: only the right tile is a trap. Therefore, the next tile in this new row is a trap, ^.
+ The third character considers .^^, which matches the second trap rule: its center and right tiles are traps, but its left tile is not. Therefore, this tile is also a trap, ^.
+ The last two characters in this new row match the first and third rules, respectively, and so they are both also traps, ^.
+
+After these steps, we now know the next row of tiles in the room: .^^^^. Then, we continue on to the next row, using the same rules, and get ^^..^. After determining two new rows, our map looks like this:
+
+..^^.
+.^^^^
+^^..^
+
+Here's a larger example with ten tiles per row and ten rows:
+
+.^^.^.^^^^
+^^^...^..^
+^.^^.^.^^.
+..^^...^^^
+.^^^^.^^.^
+^^..^.^^..
+^^^^..^^^.
+^..^^^^.^^
+.^^^..^.^^
+^^.^^^..^^
+
+In ten rows, this larger example has 38 safe tiles.
+
+Starting with the map in your puzzle input, in a total of 40 rows (including the starting row), how many safe tiles are there?
+
diff --git a/src/2016/day18/input b/src/2016/day18/input
index e69de29..7500d66 100644
--- a/src/2016/day18/input
+++ b/src/2016/day18/input
@@ -0,0 +1 @@
+.^..^....^....^^.^^.^.^^.^.....^.^..^...^^^^^^.^^^^.^.^^^^^^^.^^^^^..^.^^^.^^..^.^^.^....^.^...^^.^.
diff --git a/src/2016/day18/input0 b/src/2016/day18/input0
index e69de29..a6d3b62 100644
--- a/src/2016/day18/input0
+++ b/src/2016/day18/input0
@@ -0,0 +1,10 @@
+.^^.^.^^^^
+^^^...^..^
+^.^^.^.^^.
+..^^...^^^
+.^^^^.^^.^
+^^..^.^^..
+^^^^..^^^.
+^..^^^^.^^
+.^^^..^.^^
+^^.^^^..^^