aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--makefile3
-rw-r--r--src/day24.cpp131
-rw-r--r--src/day24.py33
3 files changed, 166 insertions, 1 deletions
diff --git a/makefile b/makefile
index e14c204..07e42b8 100644
--- a/makefile
+++ b/makefile
@@ -22,7 +22,8 @@ all: bin/day01 \
22 bin/day20 \ 22 bin/day20 \
23 bin/day21 \ 23 bin/day21 \
24 bin/day22 \ 24 bin/day22 \
25 bin/day23 25 bin/day23 \
26 bin/day24
26 27
27bin: 28bin:
28 mkdir $@ 29 mkdir $@
diff --git a/src/day24.cpp b/src/day24.cpp
new file mode 100644
index 0000000..296d38a
--- /dev/null
+++ b/src/day24.cpp
@@ -0,0 +1,131 @@
1#include <cstdlib>
2#include <fstream>
3#include <iostream>
4#include <limits>
5#include <string>
6#include <tuple>
7#include <vector>
8using namespace std;
9
10using line_type = tuple<double, double, double, double, double, double>;
11using point_type = tuple<double, double>;
12using puzzle_type = vector<line_type>;
13
14template<typename T>
15int
16sgn(T val)
17{
18 return (T(0) < val) - (val < T(0));
19}
20
21puzzle_type
22read_file(string_view filename)
23{
24 fstream input{ filename };
25 puzzle_type result;
26
27 for ( string line; getline(input, line); ) {
28 const auto NFIELDS = 6;
29
30 double x, y, z, dx, dy, dz; // NOLINT
31
32 if ( sscanf(line.data(), "%lf, %lf, %lf @ %lf, %lf, %lf", &x, &y, &z, &dx, &dy, &dz) != NFIELDS ) {
33 continue;
34 }
35
36 result.emplace_back(make_tuple(x, y, z, dx, dy, dz));
37 }
38
39 return result;
40}
41
42point_type
43get_direction(line_type line)
44{
45 const auto [x, y, z, dx, dy, dz] = line;
46
47 return make_tuple(sgn(dx), sgn(dy));
48}
49
50point_type
51get_direction(line_type from, point_type to)
52{
53 const auto [x, y, z, dx, dy, dz] = from;
54 const auto [to_x, to_y] = to;
55
56 return make_tuple(sgn(to_x - x), sgn(to_y - y));
57}
58
59bool
60lint(line_type stone_a, line_type stone_b, point_type& cross_point)
61{
62 const auto p_1 = make_tuple(get<0>(stone_a), get<1>(stone_a));
63 const auto p_2 = make_tuple(get<0>(stone_a) + get<3>(stone_a), get<1>(stone_a) + get<4>(stone_a));
64
65 const auto p_3 = make_tuple(get<0>(stone_b), get<1>(stone_b));
66 const auto p_4 = make_tuple(get<0>(stone_b) + get<3>(stone_b), get<1>(stone_b) + get<4>(stone_b));
67
68 const auto a_1 = get<1>(p_2) - get<1>(p_1);
69 const auto b_1 = get<0>(p_1) - get<0>(p_2);
70 const auto c_1 = a_1 * (get<0>(p_1)) + b_1 * (get<1>(p_1));
71
72 const auto a_2 = get<1>(p_4) - get<1>(p_3);
73 const auto b_2 = get<0>(p_3) - get<0>(p_4);
74 const auto c_2 = a_2 * (get<0>(p_3)) + b_2 * (get<1>(p_3));
75
76 const auto determinant = a_1 * b_2 - a_2 * b_1;
77
78 if ( determinant == 0 ) {
79 return false;
80 }
81
82 auto p_x = (b_2 * c_1 - b_1 * c_2) / determinant;
83 auto p_y = (a_1 * c_2 - a_2 * c_1) / determinant;
84
85 cross_point = make_tuple(p_x, p_y);
86
87 return true;
88}
89
90void
91part1(const puzzle_type& input)
92{
93 const auto in_range = [](point_type point) -> bool {
94 static const auto lower_limit = 200000000000000.0;
95 static const auto upper_limit = 400000000000000.0;
96
97 const auto [x, y] = point;
98
99 return x > lower_limit && x < upper_limit && y > lower_limit && y < upper_limit;
100 };
101
102 const auto in_future = [](line_type stone, point_type point) -> bool {
103 const auto sgn_stone = get_direction(stone);
104 const auto sgn_point = get_direction(stone, point);
105
106 return sgn_stone == sgn_point;
107 };
108
109 long sum = 0;
110 for ( size_t idx = 0; idx != input.size(); ++idx ) {
111 const auto& stone_a = input[idx];
112
113 for ( size_t idx2 = idx + 1; idx2 < input.size(); ++idx2 ) {
114 const auto& stone_b = input[idx2];
115
116 point_type cross_point;
117 if ( lint(stone_a, stone_b, cross_point) && in_range(cross_point) && in_future(stone_a, cross_point) && in_future(stone_b, cross_point) ) {
118 ++sum;
119 }
120 }
121 }
122 cout << sum << endl;
123}
124
125int
126main()
127{
128 const auto input = read_file("data/day24.txt");
129
130 part1(input);
131}
diff --git a/src/day24.py b/src/day24.py
new file mode 100644
index 0000000..809f2d0
--- /dev/null
+++ b/src/day24.py
@@ -0,0 +1,33 @@
1class Hailstone:
2 def __init__(self, sx, sy, sz, vx, vy, vz):
3 self.sx = sx
4 self.sy = sy
5 self.sz = sz
6 self.vx = vx
7 self.vy = vy
8 self.vz = vz
9
10 self.a = vy
11 self.b = -vx
12 self.c = vy * sx - vx * sy
13
14 def __repr__(self):
15 return "Hailstone{" + f"a={self.a}, b={self.b}, c={self.c}" + "}"
16
17hailstones = [Hailstone(*map(int, line.replace("@", ",").split(","))) for line in open("data/day24.txt")]
18
19total = 0
20
21for i, hs1 in enumerate(hailstones):
22 for hs2 in hailstones[:i]:
23 a1, b1, c1 = hs1.a, hs1.b, hs1.c
24 a2, b2, c2 = hs2.a, hs2.b, hs2.c
25 if a1 * b2 == b1 * a2:
26 continue
27 x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1)
28 y = (c2 * a1 - c1 * a2) / (a1 * b2 - a2 * b1)
29 if 200000000000000 <= x <= 400000000000000 and 200000000000000 <= y <= 400000000000000:
30 if all((x - hs.sx) * hs.vx >= 0 and (y - hs.sy) * hs.vy >= 0 for hs in (hs1, hs2)):
31 total += 1
32
33print(total)