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