diff --git a/d14/main.cxx b/d14/main.cxx index 48dafe6..859015e 100644 --- a/d14/main.cxx +++ b/d14/main.cxx @@ -1,15 +1,163 @@ +#include +#include +#include #include -#include +#include +#include +#include +#include +#include -using std::cout, std::endl; +using std::cout, std::endl, std::pair; -int main() { - std::ifstream file{"../d14/input.txt"}; +namespace views = std::ranges::views; + +constexpr const char content[] = { + #embed "input.txt" +}; + +namespace std { + template<> + struct hash> { + std::size_t operator()(const pair& p) const { + return std::hash{}(p.first) ^ std::hash{}(p.second); + } + }; +} +constexpr auto height{103}; +constexpr auto width{101}; + +struct Robot { + pair pos; + pair velocity; +}; + +void move_robot(Robot& r, int time) { + r.pos.first = (r.pos.first + time * r.velocity.first) % width; + r.pos.second = (r.pos.second + time * r.velocity.second) % height; + + if(r.pos.first < 0) { + r.pos.first = width + r.pos.first; + } + + if(r.pos.second < 0) { + r.pos.second = height + r.pos.second; + } +} + +std::optional get_quadrant(const pair& p) { + if(p.first == width / 2 || p.second == height / 2) { + return std::nullopt; + } + + if(p.first <= width / 2 && p.second <= height / 2) { + return 0; + } else if(p.first > width / 2 && p.second <= height / 2) { + return 1; + } else if(p.first <= width / 2 && p.second > height / 2) { + return 2; + } else { + return 3; + } + +} + +int64_t part_1() { + std::istringstream input_stream(content); std::string line; + std::vector robots = {}; + + while(getline(input_stream, line)) { + if(line.empty()) { + continue; + } + std::replace_if(line.begin(), line.end(), [](char c) { return !std::isdigit(c) && c != '-'; }, ' '); + Robot r; + std::istringstream iss(line); + iss >> r.pos.first >> r.pos.second >> r.velocity.first >> r.velocity.second; + robots.push_back(r); + } + + std::vector quadrant_count(4, 0); + constexpr auto time{100}; + for(auto& r : robots) { + move_robot(r, time); + auto q = get_quadrant(r.pos); + if(q.has_value()) { + quadrant_count[q.value()]++; + } + } + + auto safety_factor = std::accumulate(quadrant_count.begin(), quadrant_count.end(), 1, std::multiplies()); + return safety_factor; +} + +void print_robots(const std::vector& robots) { + std::unordered_map, char> grid; + for(auto& r : robots) { + grid[r.pos] = '#'; + } + + for(auto i = 0; i < height; i++) { + for(auto j = 0; j < width; j++) { + if(grid.contains({j, i})) { + cout << grid[{j, i}]; + } else { + cout << '.'; + } + } + cout << endl; + } +} + +int64_t part_2() { + std::istringstream input_stream(content); + std::string line; + std::vector robots = {}; + + while(getline(input_stream, line)) { + if(line.empty()) { + continue; + } + std::replace_if(line.begin(), line.end(), [](char c) { return !std::isdigit(c) && c != '-'; }, ' '); + Robot r; + std::istringstream iss(line); + iss >> r.pos.first >> r.pos.second >> r.velocity.first >> r.velocity.second; + robots.push_back(r); + } + + auto time_to_tree = 0; // (ttt) + while(true) { + time_to_tree++; + for(auto& r : robots) { + move_robot(r, 1); + } + + auto count = 0; + for(auto& r : robots) { + count = std::count_if(robots.begin(), robots.end(), [&r](const Robot& r2) { + return std::abs(r.pos.first - r2.pos.first) <= 2 && std::abs(r.pos.second - r2.pos.second) <= 2; + }); + } + + // for my input 20 was the magic number + if(count >= 20) { + print_robots(robots); + break; + } - while (std::getline(file, line)) { - } + return time_to_tree; +} + +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; }