aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2024-12-15 11:15:46 +0100
committerThomas Schmucker <ts@its1.de>2024-12-15 11:15:46 +0100
commitba8010034e9873cce1a0e20397e69fab460c07ac (patch)
treeb69d3364db7ba87a87de8c266df91e9b962898de
parentdf89ce46eebb355acf353600b148de52641f060c (diff)
downloadadvent-of-code-ba8010034e9873cce1a0e20397e69fab460c07ac.tar.gz
advent-of-code-ba8010034e9873cce1a0e20397e69fab460c07ac.tar.bz2
advent-of-code-ba8010034e9873cce1a0e20397e69fab460c07ac.zip
aoc 2024, day 15, part 1
-rw-r--r--2024/src/day15.cpp144
1 files changed, 144 insertions, 0 deletions
diff --git a/2024/src/day15.cpp b/2024/src/day15.cpp
new file mode 100644
index 0000000..e11661e
--- /dev/null
+++ b/2024/src/day15.cpp
@@ -0,0 +1,144 @@
1#include <fstream>
2#include <iostream>
3#include <map>
4#include <optional>
5#include <set>
6#include <string>
7#include <tuple>
8using namespace std;
9
10using pos_type = tuple<size_t, size_t>;
11using room_type = set<pos_type>;
12using boxes_type = set<pos_type>;
13using puzzle_type = tuple<room_type, boxes_type, string, pos_type>;
14
15puzzle_type
16read_file(string_view filename)
17{
18 fstream input{ filename };
19 room_type room;
20 boxes_type boxes;
21 string movements;
22 pos_type start;
23
24 size_t yPos = 0;
25 for ( string line; getline(input, line); ) {
26 if ( line.empty() ) {
27 continue;
28 }
29
30 if ( line[0] == '#' ) {
31 for ( size_t xPos = 0; xPos != line.size(); ++xPos ) {
32 auto chr = line.at(xPos);
33 if ( chr == '#' ) {
34 room.emplace(xPos, yPos);
35 }
36 else if ( chr == 'O' ) {
37 boxes.emplace(xPos, yPos);
38 }
39 else if ( chr == '@' ) {
40 start = { xPos, yPos };
41 }
42 }
43 ++yPos;
44 }
45 else {
46 movements += line;
47 }
48 }
49
50 return { room, boxes, movements, start };
51}
52
53void
54print(const room_type& room, const boxes_type& boxes, const pos_type& pos)
55{
56 for ( size_t yPos = 0; yPos != 10; ++yPos ) {
57 for ( size_t xPos = 0; xPos != 10; ++xPos ) {
58 if ( pos == pos_type{ xPos, yPos } ) {
59 cout << '@';
60 }
61 else if ( room.contains({ xPos, yPos }) ) {
62 cout << '#';
63 }
64 else if ( boxes.contains({ xPos, yPos }) ) {
65 cout << 'O';
66 }
67 else {
68 cout << ' ';
69 }
70 }
71 cout << '\n';
72 }
73 cout << endl;
74}
75
76optional<boxes_type>
77can_move(const room_type& room, const boxes_type& boxes, pos_type start, pos_type direction) // NOLINT
78{
79 const auto [x, y] = start;
80 const auto [dx, dy] = direction;
81
82 boxes_type candidates;
83
84 size_t steps = 1;
85 while ( boxes.contains({ x + dx * steps, y + dy * steps }) ) {
86 candidates.insert({ x + dx * steps, y + dy * steps });
87 ++steps;
88 }
89
90 if ( room.contains({ x + dx * steps, y + dy * steps }) ) {
91 return nullopt;
92 }
93
94 return candidates;
95}
96
97void
98part1(const puzzle_type& puzzle)
99{
100 map<char, pos_type> deltas = {
101 { '<', { -1, 0 } }, // Left
102 { '^', { 0, -1 } }, // Up
103 { '>', { 1, 0 } }, // Right
104 { 'v', { 0, 1 } } // Down
105 };
106
107 auto [room, boxes, movements, start] = puzzle;
108
109 for ( auto chr: movements ) {
110 const auto delta = deltas[chr];
111 if ( auto bitw = can_move(room, boxes, start, delta) ) {
112 const auto [dx, dy] = delta;
113
114 get<0>(start) += dx;
115 get<1>(start) += dy;
116
117 boxes_type new_boxes;
118 for ( const auto& box: boxes ) {
119 if ( bitw->contains(box) ) {
120 const auto [x, y] = box;
121 new_boxes.emplace(x + dx, y + dy);
122 bitw->erase(box);
123 }
124 else {
125 new_boxes.insert(box);
126 }
127 }
128 boxes = new_boxes;
129 }
130 }
131
132 size_t sum = 0;
133 for (const auto& [x, y]: boxes) {
134 sum += x + 100 * y;
135 }
136 cout << sum << endl;
137}
138
139int
140main()
141{
142 const auto data = read_file("data/day15.txt");
143 part1(data);
144}