diff options
| author | Thomas Schmucker <ts@its1.de> | 2023-12-29 12:16:59 +0100 |
|---|---|---|
| committer | Thomas Schmucker <ts@its1.de> | 2023-12-29 12:16:59 +0100 |
| commit | 0d06788586cda1b1ba01524f4ba3cad147052203 (patch) | |
| tree | 26e0bfbfaa07d2edf407a9ad24209f21486e35b5 /src/day24.cpp | |
| parent | d6ae60aed827c742de956194223b4640b5403b72 (diff) | |
| download | advent-of-code-0d06788586cda1b1ba01524f4ba3cad147052203.tar.gz advent-of-code-0d06788586cda1b1ba01524f4ba3cad147052203.tar.bz2 advent-of-code-0d06788586cda1b1ba01524f4ba3cad147052203.zip | |
Lösungen für Tag 24, Teil 1
Diffstat (limited to 'src/day24.cpp')
| -rw-r--r-- | src/day24.cpp | 131 |
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> | ||
| 8 | using namespace std; | ||
| 9 | |||
| 10 | using line_type = tuple<double, double, double, double, double, double>; | ||
| 11 | using point_type = tuple<double, double>; | ||
| 12 | using puzzle_type = vector<line_type>; | ||
| 13 | |||
| 14 | template<typename T> | ||
| 15 | int | ||
| 16 | sgn(T val) | ||
| 17 | { | ||
| 18 | return (T(0) < val) - (val < T(0)); | ||
| 19 | } | ||
| 20 | |||
| 21 | puzzle_type | ||
| 22 | read_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 | |||
| 42 | point_type | ||
| 43 | get_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 | |||
| 50 | point_type | ||
| 51 | get_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 | |||
| 59 | bool | ||
| 60 | lint(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 | |||
| 90 | void | ||
| 91 | part1(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 | |||
| 125 | int | ||
| 126 | main() | ||
| 127 | { | ||
| 128 | const auto input = read_file("data/day24.txt"); | ||
| 129 | |||
| 130 | part1(input); | ||
| 131 | } | ||
