aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--makefile3
-rw-r--r--src/day17.cpp112
2 files changed, 114 insertions, 1 deletions
diff --git a/makefile b/makefile
index 539cc3c..0ce0a6f 100644
--- a/makefile
+++ b/makefile
@@ -15,7 +15,8 @@ all: bin/day01 \
15 bin/day13 \ 15 bin/day13 \
16 bin/day14 \ 16 bin/day14 \
17 bin/day15 \ 17 bin/day15 \
18 bin/day16 18 bin/day16 \
19 bin/day17
19 20
20bin: 21bin:
21 mkdir $@ 22 mkdir $@
diff --git a/src/day17.cpp b/src/day17.cpp
new file mode 100644
index 0000000..4098bba
--- /dev/null
+++ b/src/day17.cpp
@@ -0,0 +1,112 @@
1#include <array>
2#include <fstream>
3#include <functional>
4#include <iostream>
5#include <queue>
6#include <set>
7#include <string>
8#include <vector>
9using namespace std;
10
11using puzzle_t = vector<vector<int>>;
12
13puzzle_t
14read_file(string_view filename)
15{
16 fstream input{ filename };
17 puzzle_t data;
18
19 for ( string line; getline(input, line); ) {
20 puzzle_t::value_type numbers;
21 for ( auto chr: line ) {
22 numbers.emplace_back(chr - '0');
23 }
24 data.emplace_back(numbers);
25 }
26
27 return data;
28}
29
30int
31solve(const puzzle_t& puzzle, size_t min_steps, size_t max_steps)
32{
33 using pos_t = tuple<size_t, size_t>;
34 using dir_t = tuple<size_t, size_t>;
35 using entry = tuple<int, pos_t, dir_t>;
36
37 static const array<pos_t, 4> directions = {
38 make_tuple(0, 1),
39 make_tuple(0, -1),
40 make_tuple(1, 0),
41 make_tuple(-1, 0)
42 };
43
44 priority_queue<entry, vector<entry>, greater<>> queue;
45
46 set<tuple<pos_t, dir_t>> seen;
47
48 const pos_t target = { puzzle.size() - 1, puzzle[0].size() - 1 };
49
50 queue.emplace(0, pos_t(0, 0), dir_t(0, 0));
51
52 while ( !queue.empty() ) {
53 const auto [heat, pos, dir] = queue.top();
54 queue.pop();
55
56 if ( pos == target ) {
57 return heat;
58 }
59
60 const auto key = make_tuple(pos, dir);
61 if ( seen.contains(key) ) {
62 continue;
63 }
64 seen.emplace(key);
65
66 const dir_t inv_dir = { -get<0>(dir), -get<1>(dir) };
67
68 for ( const auto& next_dir: directions ) {
69 if ( next_dir == dir || next_dir == inv_dir ) {
70 continue;
71 }
72
73 auto heat_so_far = heat;
74
75 for ( size_t steps = 1; steps <= max_steps; ++steps ) {
76 const pos_t next_pos = { get<0>(pos) + get<0>(next_dir) * steps,
77 get<1>(pos) + get<1>(next_dir) * steps };
78
79 if ( get<0>(next_pos) >= puzzle.size() || get<1>(next_pos) >= puzzle[0].size() ) {
80 continue;
81 }
82
83 heat_so_far += puzzle[get<0>(next_pos)][get<1>(next_pos)];
84
85 if ( steps >= min_steps ) {
86 queue.emplace(heat_so_far, next_pos, next_dir);
87 }
88 }
89 }
90 }
91 return -1;
92}
93
94void
95part1(const puzzle_t& puzzle)
96{
97 cout << solve(puzzle, 1, 3) << endl;
98}
99
100void
101part2(const puzzle_t& puzzle)
102{
103 cout << solve(puzzle, 4, 10) << endl;
104}
105
106int
107main()
108{
109 const auto puzzle = read_file("data/day17.txt");
110 part1(puzzle);
111 part2(puzzle);
112}