aboutsummaryrefslogtreecommitdiff
path: root/2024/16/day16a.cpp
diff options
context:
space:
mode:
authorSebastiano Tronto <sebastiano@tronto.net>2024-12-16 09:33:38 +0100
committerSebastiano Tronto <sebastiano@tronto.net>2024-12-16 09:33:38 +0100
commit5a725f1b9e8cfbad2c31d9c220061e413adbbf8e (patch)
tree70119de6d0fa800851ed25f53e02b0474c8fa0cb /2024/16/day16a.cpp
parent9ecea0012b98f42debd536dc863b4ef2501eb859 (diff)
downloadaoc-5a725f1b9e8cfbad2c31d9c220061e413adbbf8e.tar.gz
aoc-5a725f1b9e8cfbad2c31d9c220061e413adbbf8e.zip
Day 16 2024
Diffstat (limited to '2024/16/day16a.cpp')
-rw-r--r--2024/16/day16a.cpp180
1 files changed, 180 insertions, 0 deletions
diff --git a/2024/16/day16a.cpp b/2024/16/day16a.cpp
new file mode 100644
index 0000000..28e852c
--- /dev/null
+++ b/2024/16/day16a.cpp
@@ -0,0 +1,180 @@
1#include <algorithm>
2#include <cstdint>
3#include <iostream>
4#include <queue>
5#include <string>
6#include <string_view>
7#include <vector>
8#include <set>
9using namespace std;
10
11class Direction {
12public:
13 int U, R;
14
15 Direction(char c) :
16 U{c == 'v' ? 1 : (c == '^' ? -1 : 0)},
17 R{c == '>' ? 1 : (c == '<' ? -1 : 0)} {}
18
19 Direction(const int i, const int j) : U{i}, R{j} {}
20
21 Direction turnright() const {
22 return turn(-1, 0);
23 }
24
25 Direction turnleft() const {
26 return turn(1, 0);
27 }
28
29 bool operator<(const Direction& d) const { // For set<Direction>
30 return this->U < d.U || (this->U == d.U && this->R < d.R);
31 }
32
33 int index() const {
34 if (U == 1 && R == 0) return 0;
35 if (U == -1 && R == 0) return 1;
36 if (U == 0 && R == 1) return 2;
37 if (U == 0 && R == -1) return 3;
38 return -1;
39 }
40private:
41 Direction turn(int64_t sin, int64_t cos) const {
42 return Direction(cos * U - sin * R, sin * U + cos * R);
43 }
44};
45
46class Position {
47public:
48 int64_t i, j;
49
50 Position() : Position(0, 0) {}
51
52 Position(int64_t a, int64_t b) : i{a}, j{b} {}
53
54 Position step(const Direction d) const {
55 return Position(i+d.U, j+d.R);
56 }
57};
58
59const Direction all_directions[] = {
60 Direction(1, 0), Direction(-1, 0), Direction(0, 1), Direction(0, -1)
61};
62
63class Qelem {
64public:
65 int64_t distance;
66 Position p;
67 Direction d;
68
69 Qelem(int dis, Position pp, Direction dd) :
70 distance{dis}, p{pp}, d{dd} {}
71
72 bool operator<(const Qelem& other) const {
73 return distance > other.distance;
74 }
75};
76
77class Board {
78public:
79 int64_t N, M;
80
81 Board(const vector<string>& lines) :
82 N{static_cast<int64_t>(lines.size())},
83 M{static_cast<int64_t>(lines[0].size())},
84 cells(M*N), visited(4*M*N)
85 {
86 for (int64_t i = 0; i < N; i++)
87 for (int64_t j = 0; j < M; j++)
88 cells[M*i+j] = lines[i][j];
89 }
90
91 char& operator[](const Position p) {
92 if (const auto c = coord(p); c == -1)
93 return out_of_bound;
94 else
95 return cells[c];
96 }
97
98 Position find_S() {
99 for (Position p(0, 0); p.i < N; p.i++)
100 for (p.j = 0; p.j < M; p.j++)
101 if ((*this)[p] == 'S')
102 return p;
103 return Position(-1, -1);
104 }
105
106 int shortest_path(Position p, Direction d) {
107 clear_visited();
108 priority_queue<Qelem> q;
109
110 q.push(Qelem(0, p, d));
111
112 while (!q.empty()) {
113 auto e = q.top();
114 q.pop();
115
116 if ((*this)[e.p] == 'E')
117 return e.distance;
118
119 if (is_visited(e.p, e.d) || (*this)[e.p] == '#')
120 continue;
121 set_visited(e.p, e.d);
122
123 q.push(Qelem(e.distance+1000, e.p, e.d.turnright()));
124 q.push(Qelem(e.distance+1000, e.p, e.d.turnleft()));
125 q.push(Qelem(e.distance+1, e.p.step(e.d), e.d));
126 }
127 return 999999999;
128 }
129
130 void print() {
131 for (Position p(0, 0); p.i < N; p.i++) {
132 for (p.j = 0; p.j < M; p.j++)
133 cout << (*this)[p];
134 cout << endl;
135 }
136 }
137private:
138 char out_of_bound = '$';
139
140 vector<char> cells;
141 vector<bool> visited;
142
143 int64_t coord(const Position p) const {
144 auto [i, j] = p;
145 return i >= N || i < 0 || j >= M || j < 0 ? -1 : M * i + j;
146 }
147
148 void clear_visited() {
149 for (int64_t i = 0; i < 4*M*N; i++)
150 visited[i] = false;
151 }
152
153 bool is_visited(const Position p, const Direction d) {
154 if (const auto c = coord(p); c == -1)
155 return false;
156 else
157 return visited[4*c + d.index()];
158 }
159
160 void set_visited(const Position p, const Direction d) {
161 if (const auto c = coord(p); c != -1)
162 visited[4*c + d.index()] = true;
163 }
164};
165
166int main() {
167 string line;
168 vector<string> lines;
169
170 while (getline(cin, line))
171 lines.push_back(line);
172
173 Board board(lines);
174 Direction d('>');
175 Position p = board.find_S();
176
177 cout << board.shortest_path(p, d) << endl;
178
179 return 0;
180}

Generated with cgit - Back to sebastiano.tronto.net