aboutsummaryrefslogtreecommitdiff
path: root/src/day24.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/day24.cpp')
-rw-r--r--src/day24.cpp131
1 files changed, 131 insertions, 0 deletions
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}