Line data Source code
1 : #include "LinewiseInput.h"
2 : #include "PuzzleImpl.h"
3 : #include "Vector.h"
4 :
5 : #include <libassert/assert.hpp>
6 : #include <re2/re2.h>
7 :
8 : #include <string>
9 : #include <string_view>
10 : #include <vector>
11 :
12 : namespace {
13 :
14 : struct Hailstone2d {
15 300 : Hailstone2d(std::string_view const line) {
16 300 : static const RE2 pattern = R"((\d+), +(\d+), +\d+ @ +(-?\d+), +(-?\d+), +-?\d+)";
17 300 : ASSUME(RE2::FullMatch(line, pattern, &pos[0], &pos[1], &vel[0], &vel[1]));
18 300 : }
19 :
20 : Vec2<double> pos;
21 : Vec2<double> vel;
22 : };
23 :
24 44850 : std::optional<Vec2<double>> intersect(Hailstone2d const &a, Hailstone2d const &b) {
25 44850 : double const dx = b.pos[0] - a.pos[0];
26 44850 : double const dy = b.pos[1] - a.pos[1];
27 44850 : double const det = b.vel[0] * a.vel[1] - b.vel[1] * a.vel[0];
28 44850 : double const u = (dy * b.vel[0] - dx * b.vel[1]) / det;
29 44850 : double const v = (dy * a.vel[0] - dx * a.vel[1]) / det;
30 44850 : if (u > 0.0 && v > 0.0)
31 24547 : return a.pos + a.vel * u;
32 20303 : else
33 20303 : return std::nullopt;
34 44850 : }
35 :
36 24547 : template <size_t N> bool inTestArea(Vector<N, double> const &v) {
37 24547 : return std::ranges::all_of(
38 46060 : v, [](double const d) { return d >= 200000000000000.0 && d <= 400000000000000.0; });
39 24547 : }
40 :
41 : } // namespace
42 :
43 1 : template <> std::string solvePart1<2023, 24>(std::string_view const input) {
44 1 : LinewiseInput lines(input);
45 :
46 1 : std::vector<Hailstone2d> hailstones(lines.begin(), lines.end());
47 :
48 1 : size_t ctr = 0;
49 301 : for (auto it = hailstones.begin(); it != hailstones.end(); ++it)
50 45150 : for (auto it2 = std::next(it); it2 != hailstones.end(); ++it2) {
51 44850 : auto intersectPoint = intersect(*it, *it2);
52 44850 : if (intersectPoint && inTestArea(*intersectPoint))
53 15262 : ++ctr;
54 44850 : }
55 :
56 1 : return std::to_string(ctr);
57 1 : }
58 :
59 1 : template <> std::string solvePart2<2023, 24>(std::string_view const /*input*/) { return ""; }
|