Skip to content

Commit 77fd39b

Browse files
author
Christian Lundh
committed
C++23 2024 day 14 (Update)
Simplifications, more const, unordered_set...
1 parent 5fccf4f commit 77fd39b

File tree

1 file changed

+47
-53
lines changed

1 file changed

+47
-53
lines changed

C++/2024/aoc_2024_14.cpp

Lines changed: 47 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,46 @@
44
#include <cstdint>
55
#include <iterator>
66
#include <ranges>
7-
#include <set>
7+
#include <unordered_set>
88
#include <vector>
99

10-
using Robot = std::pair<std::pair<int, int>, std::pair<int, int>>;
10+
using Point = std::pair<int, int>;
11+
using Robot = std::pair<Point, Point>;
12+
13+
template <>
14+
struct std::hash<std::pair<int, int>> {
15+
auto operator()(const pair<int, int> &v) const -> size_t {
16+
return std::hash<int>()(v.first) ^ std::hash<int>()(v.second);
17+
}
18+
};
1119

1220
[[nodiscard]] auto parse_instructions(const std::vector<std::string> &instructions) -> std::vector<Robot> {
1321
auto robots = std::vector<Robot>{};
1422
std::ranges::transform(instructions, std::back_inserter(robots), [](const auto &s) -> Robot {
15-
auto s1 = s.substr(s.find('=') + 1, s.find(' '));
16-
auto s2 = s.substr(s.find('v') + 2, s.npos);
17-
auto p1 = std::stoi(s1);
18-
auto p2 = std::stoi(s1.substr(s1.find(',') + 1, s1.npos));
19-
auto p3 = std::stoi(s2);
20-
auto p4 = std::stoi(s2.substr(s2.find(',') + 1, s2.npos));
21-
22-
auto pp1 = std::pair{p1, p2};
23-
auto pp2 = std::pair{p3, p4};
24-
return {pp1, pp2};
23+
const auto s1 = s.substr(s.find('=') + 1, s.find(' '));
24+
const auto s2 = s.substr(s.find('v') + 2, s.npos);
25+
const auto p1 = std::stoi(s1);
26+
const auto p2 = std::stoi(s1.substr(s1.find(',') + 1, s1.npos));
27+
const auto p3 = std::stoi(s2);
28+
const auto p4 = std::stoi(s2.substr(s2.find(',') + 1, s2.npos));
29+
30+
return {
31+
std::pair{p1, p2},
32+
std::pair{p3, p4}
33+
};
2534
});
2635
return robots;
2736
}
2837

29-
void move_robot(Robot &r, const auto &steps) {
38+
void move_robot(Robot &r, const auto steps, const auto &limits) {
3039
auto &[position, velocity] = r;
3140
auto &[x, y] = position;
3241
auto &[vx, vy] = velocity;
3342

34-
x += steps * vx;
35-
y += steps * vy;
43+
auto &[max_x, max_y] = limits;
44+
45+
x = (max_x + (x + steps * vx) % max_x) % max_x;
46+
y = (max_y + (y + steps * vy) % max_y) % max_y;
3647
}
3748

3849
auto get_limits(const std::vector<Robot> &robots) {
@@ -49,33 +60,22 @@ auto get_limits(const std::vector<Robot> &robots) {
4960
const auto iterations = 100;
5061
std::vector<Robot> robots = instructions;
5162

52-
const auto [max_x, max_y] = get_limits(instructions);
53-
for (auto &robot : robots) {
54-
move_robot(robot, iterations);
55-
auto &[position, velocity] = robot;
56-
position.first = position.first % max_x;
57-
position.second = position.second % max_y;
58-
if (position.first < 0)
59-
position.first += max_x;
60-
if (position.second < 0)
61-
position.second += max_y;
62-
}
63+
const auto limits = get_limits(instructions);
64+
const auto [max_x, max_y] = limits;
65+
std::ranges::for_each(robots, [&](auto &robot) {
66+
move_robot(robot, iterations, limits);
67+
});
6368

64-
const auto quadrants = std::vector<std::pair<std::pair<int, int>, std::pair<int, int>>>{
65-
{{0, 0}, {max_x / 2, max_y / 2}},
66-
{{max_x / 2 + 1, 0}, {max_x, max_y / 2} },
67-
{{0, max_y / 2 + 1}, {max_x / 2, max_y} },
68-
{{max_x / 2 + 1, max_y / 2 + 1}, {max_x, max_y} }
69+
const auto quadrants = std::array<std::pair<Point, Point>, 4>{
70+
{{{0, 0}, {max_x / 2, max_y / 2}}, {{max_x / 2 + 1, 0}, {max_x, max_y / 2}}, {{0, max_y / 2 + 1}, {max_x / 2, max_y}}, {{max_x / 2 + 1, max_y / 2 + 1}, {max_x, max_y}}}
6971
};
7072

7173
auto result = uint32_t{1};
7274
for (auto &quadrant : quadrants) {
7375
result *= std::ranges::count_if(robots, [&quadrant](const auto &r) {
7476
auto [position, velocity] = r;
7577
auto [l1, l2] = quadrant;
76-
if (!((l1.first <= position.first) && (position.first < l2.first)))
77-
return false;
78-
if (!((l1.second <= position.second) && (position.second < l2.second)))
78+
if (!((l1.first <= position.first) && (position.first < l2.first) && (l1.second <= position.second) && (position.second < l2.second)))
7979
return false;
8080
return true;
8181
});
@@ -84,30 +84,24 @@ auto get_limits(const std::vector<Robot> &robots) {
8484
}
8585

8686
auto all_unique_positions(const std::vector<Robot> &robots) -> bool {
87-
auto field = std::set<std::pair<int, int>>{};
88-
std::ranges::for_each(robots, [&field](const auto &r) {
89-
field.insert({r.first.first, r.first.second});
90-
});
91-
return (robots.size() == field.size());
87+
auto field = std::unordered_set<Point>{};
88+
for (auto &robot : robots) {
89+
auto [it, success] = field.insert(robot.first);
90+
if (!success)
91+
return false;
92+
}
93+
return true;
9294
}
9395

9496
[[nodiscard]] auto solve_part_2(const std::vector<Robot> &instructions) -> int {
9597

9698
std::vector<Robot> robots = instructions;
97-
auto [max_x, max_y] = get_limits(instructions);
98-
auto result = int{};
99-
while (!all_unique_positions(robots)) {
100-
for (auto &robot : robots) {
101-
move_robot(robot, 1);
102-
auto &[position, velocity] = robot;
103-
position.first = position.first % max_x;
104-
position.second = position.second % max_y;
105-
if (position.first < 0)
106-
position.first += max_x;
107-
if (position.second < 0)
108-
position.second += max_y;
109-
}
110-
++result;
99+
const auto limits = get_limits(instructions);
100+
auto result = int{};
101+
for (; !all_unique_positions(robots); ++result) {
102+
std::ranges::for_each(robots, [&](auto &robot) {
103+
move_robot(robot, 1, limits);
104+
});
111105
}
112106
return result;
113107
}

0 commit comments

Comments
 (0)