Skip to content

Commit 59f630b

Browse files
committed
12
1 parent 2c26807 commit 59f630b

File tree

4 files changed

+103
-7
lines changed

4 files changed

+103
-7
lines changed

Diff for: cpp/12.cpp

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include "common.h"
2+
3+
namespace {
4+
#define NOT_FOUND -1
5+
using Pos = std::complex<size_t>;
6+
using Heading = std::complex<long>;
7+
8+
long solve(const auto &input, Pos st, Pos end) {
9+
size_t m = input.size(), n = input[0].size();
10+
11+
auto hasher = [](const Pos &k) -> std::size_t {
12+
return std::hash<long>()(k.real()) ^ std::hash<long>()(k.imag());
13+
};
14+
auto within_bounds = [&m, &n](const Heading &v) -> bool {
15+
return v.imag() >= 0 && v.real() >= 0 && v.imag() < static_cast<long>(n) &&
16+
v.real() < static_cast<long>(m);
17+
};
18+
auto within_height = [&input](const Pos &u, const Heading &v) -> bool {
19+
return (input[v.real()][v.imag()] - input[u.real()][u.imag()] <= 1);
20+
};
21+
std::array<Heading, 4> dirs = {Heading{-1, 0}, Heading{1, 0}, Heading{0, -1},
22+
Heading{0, 1}};
23+
std::deque<std::tuple<Pos, long>> frontier{{st, 0}};
24+
std::unordered_set<Pos, decltype(hasher)> visited{st};
25+
long res{NOT_FOUND};
26+
while (frontier.size() > 0 && res == NOT_FOUND) {
27+
const auto &[u, d] = frontier.front();
28+
if (u == end) {
29+
res = d;
30+
continue;
31+
}
32+
for (const auto &dir : dirs) {
33+
Heading v = dir + static_cast<Heading>(u);
34+
if (!visited.contains(static_cast<Pos>(v)) && within_bounds(v) &&
35+
within_height(u, v)) {
36+
frontier.push_back({v, d + 1});
37+
visited.emplace(v);
38+
}
39+
}
40+
frontier.pop_front();
41+
}
42+
return res;
43+
}
44+
45+
long p1(auto input) {
46+
Pos st{}, end{};
47+
for (size_t i{0}; const auto &line : input) {
48+
if (size_t j{0}; (j = line.find("S")) != std::string::npos)
49+
st = Pos{i, j};
50+
if (size_t j{0}; (j = line.find("E")) != std::string::npos)
51+
end = Pos{i, j};
52+
++i;
53+
}
54+
input[st.real()][st.imag()] = 'a';
55+
input[end.real()][end.imag()] = 'z';
56+
57+
const auto res = solve(input, st, end);
58+
ASSERT_EXPR(res != NOT_FOUND, "Failed to find solution");
59+
return res;
60+
}
61+
62+
long p2(auto input) {
63+
size_t m = input.size(), n = input[0].size();
64+
65+
std::vector<Pos> strts{};
66+
Pos end{};
67+
for (size_t i{0}; i < m; ++i) {
68+
for (size_t j{0}; j < n; ++j) {
69+
if (input[i][j] == 'a' || input[i][j] == 'S') {
70+
strts.emplace_back(Pos{i, j});
71+
input[i][j] = 'a';
72+
}
73+
if (input[i][j] == 'E') {
74+
end = Pos{i, j};
75+
input[i][j] = 'z';
76+
}
77+
}
78+
}
79+
80+
std::vector<long> res{};
81+
for (const auto &st : strts) {
82+
const auto t = solve(input, st, end);
83+
if (t != NOT_FOUND)
84+
res.emplace_back(t);
85+
}
86+
ASSERT_EXPR(res.size() != 0, "Failed to find solution");
87+
return std::ranges::min(res);
88+
}
89+
} // namespace
90+
91+
int main() {
92+
const auto &input = gb::advent2021::readIn();
93+
gb::advent2021::writeOut(std::to_string(p1(input)));
94+
gb::advent2021::writeOut(std::to_string(p2(input)));
95+
}

Diff for: cpp/7.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ struct Dir {
44
std::string name;
55
long size;
66
};
7-
#define ASSERT_EXPR(expr, err) \
8-
if ((expr)) \
9-
throw std::runtime_error((err));
7+
108
#define ASSERT_SCAN(expr, err) \
119
if ((expr) == 0) \
1210
throw std::runtime_error((err));
@@ -17,7 +15,7 @@ Dir solve(size_t &i, const auto &input, auto &dirs) {
1715
char s[MaxSize];
1816
ASSERT_SCAN(sscanf(input[i++].c_str(), "$ cd %s", s), "No cd");
1917
d.name = s;
20-
ASSERT_EXPR(input[i++] != "$ ls", "No ls");
18+
ASSERT_EXPR(input[i++] == "$ ls", "No ls");
2119
while (i < input.size() && input[i][0] != '$') {
2220
long sz{};
2321
if (input[i].find("dir") == std::string::npos)

Diff for: cpp/common.h

+3
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
#include <vector>
2929

3030
using vs = std::vector<std::string>;
31+
#define ASSERT_EXPR(expr, err) \
32+
if (!(expr)) \
33+
throw std::runtime_error((err));
3134

3235
namespace gb::advent2021 {
3336

Diff for: cpp/meson.build

+3-3
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@ executable('11',
4848
# dependencies: [gmp])
4949
dependencies: [])
5050

51-
# executable('12',
52-
# '12.cpp',
53-
# dependencies: [])
51+
executable('12',
52+
'12.cpp',
53+
dependencies: [])
5454

5555
# executable('13',
5656
# '13.cpp',

0 commit comments

Comments
 (0)