aboutsummaryrefslogtreecommitdiff
path: root/2016/src/day24.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2016/src/day24.cpp')
-rw-r--r--2016/src/day24.cpp153
1 files changed, 153 insertions, 0 deletions
diff --git a/2016/src/day24.cpp b/2016/src/day24.cpp
new file mode 100644
index 0000000..936f216
--- /dev/null
+++ b/2016/src/day24.cpp
@@ -0,0 +1,153 @@
1#include <filesystem>
2#include <fstream>
3#include <iostream>
4#include <map>
5#include <queue>
6#include <set>
7#include <string>
8
9using namespace std;
10
11namespace {
12
13using pos_type = tuple<size_t, size_t>;
14using grid_type = map<pos_type, char>;
15using points_type = map<char, pos_type>;
16using dists_type = map<tuple<char, char>, size_t>;
17
18tuple<grid_type, points_type>
19read_file(const filesystem::path& filename)
20{
21 ifstream file{ filename };
22
23 grid_type grid;
24 points_type points;
25
26 size_t row = 0;
27 for ( string line; getline(file, line); ) {
28 for ( size_t col = 0; col != line.size(); ++col ) {
29 auto chr = line[col];
30 pos_type pos{ col, row };
31
32 grid[pos] = chr;
33
34 if ( isdigit(chr) != 0 ) {
35 points[chr] = pos;
36 }
37 }
38
39 ++row;
40 }
41 return { grid, points };
42}
43
44size_t
45bfs(const grid_type& grid, const pos_type src, const pos_type dest)
46{
47 set<pos_type> seen;
48 queue<tuple<pos_type, size_t>> queue;
49
50 queue.emplace(src, 0);
51 seen.insert(src);
52
53 while ( !queue.empty() ) {
54 auto [pos, steps] = queue.front();
55 queue.pop();
56
57 if ( pos == dest ) {
58 return steps;
59 }
60
61 static const pos_type dirs[]{ { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
62 const auto [x, y] = pos;
63
64 for ( const auto [dx, dy]: dirs ) {
65 const pos_type new_pos{ x + dx, y + dy };
66
67 if ( grid.at(new_pos) == '#' || seen.contains(new_pos) ) {
68 continue;
69 }
70
71 seen.insert(new_pos);
72 queue.emplace(new_pos, steps + 1);
73 }
74 }
75
76 return 0;
77}
78
79dists_type
80build_dists(const grid_type& grid, const points_type& points)
81{
82 dists_type dists;
83
84 for ( auto src = points.begin(); src != points.end(); ++src ) {
85 for ( auto dest = next(src); dest != points.end(); ++dest ) {
86 const auto dist = bfs(grid, src->second, dest->second);
87
88 dists[{ src->first, dest->first }] = dist;
89 dists[{ dest->first, src->first }] = dist;
90 }
91 }
92
93 return dists;
94}
95
96size_t
97shortest_route(const dists_type& dists,
98 const points_type& points,
99 bool return_to_start)
100{
101 vector<char> others;
102 for ( const auto& [id, _]: points ) {
103 if ( id != '0' ) {
104 others.push_back(id);
105 }
106 }
107
108 size_t best = numeric_limits<size_t>::max();
109
110 do {
111 size_t dist = 0;
112 char current = '0';
113
114 for ( char next: others ) {
115 dist += dists.at({ current, next });
116 current = next;
117 }
118
119 if ( return_to_start ) {
120 dist += dists.at({ current, '0' });
121 }
122
123 best = min(best, dist);
124 } while ( next_permutation(others.begin(), others.end()) );
125
126 return best;
127}
128
129void
130part1(const grid_type& grid, const points_type& points)
131{
132 auto dists = build_dists(grid, points);
133 auto route = shortest_route(dists, points, false);
134 cout << "Part1: " << route << '\n';
135}
136
137void
138part2(const grid_type& grid, const points_type& points)
139{
140 auto dists = build_dists(grid, points);
141 auto route = shortest_route(dists, points, true);
142 cout << "Part2: " << route << '\n';
143}
144
145} // namespace
146
147int
148main()
149{
150 auto [grid, points] = read_file("data/day24.txt");
151 part1(grid, points);
152 part2(grid, points);
153}