#include #include #include #include #include #include #include #include using std::cout, std::endl; constexpr const char content[] = { #embed "input.txt" }; bool position_in_bounds(int x, int y, int max_x, int max_y) { return x >= 0 && x <= max_x && y >= 0 && y <= max_y; } namespace std { template <> struct hash> { std::size_t operator()(const std::pair& p) const { auto h1 = std::hash{}(p.first); auto h2 = std::hash{}(p.second); return h1 ^ (h2 << 1); } }; } void get_antinodes(std::unordered_set>& antinodes, std::pair a1, std::pair a2, int max_x, int max_y) { auto [x1, y1] = a1; auto [x2, y2] = a2; auto dx = x2 - x1; auto dy = y2 - y1; auto gcd = std::gcd(dx, dy); dx /= gcd; dy /= gcd; auto x_fst = x1 - dx; auto y_fst = y1 - dy; if(position_in_bounds(x_fst, y_fst, max_x, max_y)) { antinodes.insert({x_fst, y_fst}); } auto x_snd = x2 + dx; auto y_snd = y2 + dy; if(position_in_bounds(x_snd, y_snd, max_x, max_y)) { antinodes.insert({x_snd, y_snd}); } } int part_1() { std::istringstream input_stream(content); std::string line; std::unordered_map>> frequencies_map; auto row{0}, col{0}; while (std::getline(input_stream, line)) { if(line.empty()) { continue; } std::istringstream line_stream(line); char frequency; col = 0; while (line_stream >> frequency) { if(frequency != '.') { if(frequencies_map.find(frequency) == frequencies_map.end()) { frequencies_map[frequency] = {}; } frequencies_map[frequency].emplace_back(row, col); } col++; } row++; } int max_x = row - 1, max_y = col - 1; std::unordered_set> antinodes = {}; for(auto &[freq, positions] : frequencies_map) { for(auto &pos_1 : positions) { for(auto &pos_2 : positions) { if(pos_1 != pos_2) { get_antinodes(antinodes, pos_1, pos_2, max_x, max_y); } } } } return antinodes.size(); } void get_all_antinodes(std::unordered_set>& antinodes, std::pair a1, std::pair a2, int max_x, int max_y) { int num_antinodes{0}; auto [x1, y1] = a1; auto [x2, y2] = a2; auto dx = x2 - x1; auto dy = y2 - y1; auto gcd = std::gcd(dx, dy); dx /= gcd; dy /= gcd; auto x_fst = x1 - dx; auto y_fst = y1 - dy; while(position_in_bounds(x_fst, y_fst, max_x, max_y)) { antinodes.insert({x_fst, y_fst}); x_fst -= dx; y_fst -= dy; } auto x_snd = x2 + dx; auto y_snd = y2 + dy; while(position_in_bounds(x_snd, y_snd, max_x, max_y)) { antinodes.insert({x_snd, y_snd}); x_snd += dx; y_snd += dy; } } int part_2() { std::istringstream input_stream(content); std::string line; std::unordered_map>> frequencies_map; std::unordered_set> antinodes = {}; auto row{0}, col{0}; while (std::getline(input_stream, line)) { if(line.empty()) { continue; } std::istringstream line_stream(line); char frequency; col = 0; while (line_stream >> frequency) { if(frequency != '.') { if(frequencies_map.find(frequency) == frequencies_map.end()) { frequencies_map[frequency] = {}; } frequencies_map[frequency].emplace_back(row, col); antinodes.insert({row, col}); } col++; } row++; } int max_x = row - 1, max_y = col - 1; for(auto &[freq, positions] : frequencies_map) { for(auto &pos_1 : positions) { for(auto &pos_2 : positions) { if(pos_1 != pos_2) { get_all_antinodes(antinodes, pos_1, pos_2, max_x, max_y); } } } } return antinodes.size(); } int main() { std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); auto p1_val = part_1(); std::chrono::steady_clock::time_point middle = std::chrono::steady_clock::now(); auto p2_val = part_2(); std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); cout << "Part 1: " << p1_val << " (" << std::chrono::duration_cast(middle - begin).count() << "µs)" << endl; cout << "Part 2: " << p2_val << " (" << std::chrono::duration_cast(end - middle).count() << "µs)" << endl; return 0; }