mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implement day 10 part 2.
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <unordered_set>
|
||||
#include <cmath>
|
||||
#include "days.hpp"
|
||||
#include "point.hpp"
|
||||
|
||||
namespace {
|
||||
typedef aoc2019::Point<int, 2> point_t;
|
||||
|
||||
std::vector<point_t> read_points(std::istream& input) {
|
||||
std::vector<point_t> read_points(std::istream &input) {
|
||||
std::vector<point_t> result;
|
||||
|
||||
int y = 0;
|
||||
@@ -27,31 +29,88 @@ namespace {
|
||||
point_t simplify(point_t x) {
|
||||
auto gcd = std::abs(std::gcd(x[0], x[1]));
|
||||
if (gcd > 1) {
|
||||
return { x[0] / gcd, x[1] / gcd };
|
||||
return {x[0] / gcd, x[1] / gcd};
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
std::pair<std::size_t, std::size_t> part1(const std::vector<point_t> &points) {
|
||||
std::size_t best = 0;
|
||||
std::size_t best_index = 0;
|
||||
|
||||
for (std::size_t i = 0; i < points.size(); ++i) {
|
||||
std::unordered_set<point_t> visible;
|
||||
const auto point = points[i];
|
||||
|
||||
for (auto asteroid : points) {
|
||||
if (asteroid == point) continue;
|
||||
visible.insert(simplify(asteroid - point));
|
||||
}
|
||||
|
||||
if (visible.size() > best) {
|
||||
best = visible.size();
|
||||
best_index = i;
|
||||
}
|
||||
|
||||
best = std::max(visible.size(), best);
|
||||
}
|
||||
|
||||
return {best, best_index};
|
||||
}
|
||||
}
|
||||
|
||||
void aoc2019::day10_part1(std::istream &input, std::ostream &output) {
|
||||
const auto points = read_points(input);
|
||||
std::size_t best = 0;
|
||||
|
||||
for (auto point : points) {
|
||||
std::unordered_set<point_t> visible;
|
||||
auto[best, _] = part1(points);
|
||||
|
||||
for (auto asteroid : points) {
|
||||
if (asteroid == point) continue;
|
||||
visible.insert(simplify(asteroid - point));
|
||||
}
|
||||
|
||||
best = std::max(visible.size(), best);
|
||||
}
|
||||
|
||||
output << best << std::endl;
|
||||
output << best << std::endl;
|
||||
}
|
||||
|
||||
void aoc2019::day10_part2(std::istream &input, std::ostream &output) {
|
||||
output << "Not implemented\n";
|
||||
const auto points = read_points(input);
|
||||
const auto[_, base] = part1(points);
|
||||
const auto base_point = points[base];
|
||||
|
||||
std::unordered_map<point_t, std::vector<point_t>> angle_points;
|
||||
|
||||
for (auto point : points) {
|
||||
if (point == base_point) continue;
|
||||
auto diff = point - base_point;
|
||||
|
||||
angle_points[simplify(diff)].push_back(diff);
|
||||
}
|
||||
|
||||
std::vector<std::pair<float, point_t>> angles;
|
||||
|
||||
for (auto &entry : angle_points) {
|
||||
angles.emplace_back(std::atan2(entry.first[1], entry.first[0]), entry.first);
|
||||
// Sort entries in descending order of distance so we can pop_back() them
|
||||
std::sort(entry.second.begin(), entry.second.end(), [](auto a, auto b) { return a.l1() > b.l1(); });
|
||||
}
|
||||
|
||||
std::sort(angles.begin(), angles.end(), std::greater<>{});
|
||||
|
||||
const auto starting_point = std::make_pair(float(0.5 * M_PI),
|
||||
point_t{std::numeric_limits<int>::max(),
|
||||
std::numeric_limits<int>::max()});
|
||||
|
||||
auto it = std::lower_bound(angles.begin(), angles.end(), starting_point, std::greater<>{});
|
||||
|
||||
for (int hits = 0; hits < 199; ++hits) {
|
||||
angle_points[it->second].pop_back();
|
||||
|
||||
// Advance it to the next asteroid we can hit.
|
||||
while (angle_points[it->second].empty()) {
|
||||
++it;
|
||||
if (it == angles.end()) {
|
||||
it = angles.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto final_asteroid = angle_points[it->second].back() + base_point;
|
||||
|
||||
output << final_asteroid[0] * 100 + final_asteroid[1] << std::endl;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user