advent2024

Advent of Code 2024
git clone git://bsandro.tech/advent2024
Log | Files | Refs

main.cpp (3225B)


      1 #include <iostream>
      2 #include <filesystem>
      3 #include <fstream>
      4 #include <vector>
      5 #include <cstring>
      6 #include <cstdio>
      7 #include <tuple>
      8 #include <algorithm>
      9 #include <chrono>
     10 #include <thread>
     11 #include "utils.hpp"
     12 
     13 struct Vec2 {
     14     int x;
     15     int y;
     16 };
     17 
     18 struct Robot {
     19     Vec2 p; // position
     20     Vec2 v; // velocity
     21     Robot(const std::string &s) {
     22         std::sscanf(s.c_str(), "p=%d,%d v=%d,%d", &p.x, &p.y, &v.x, &v.y);
     23     }
     24 };
     25 
     26 typedef std::vector<Robot> Data;
     27 
     28 template<typename T, typename N>
     29 T read_file(const std::string &path) {
     30     std::ifstream ifs(path, std::ios::binary);
     31     if (!ifs.is_open()) {
     32         throw std::runtime_error(path+":"+std::strerror(errno));
     33     }
     34     T buf;
     35     while (1) {
     36         std::string str;
     37         std::getline(ifs, str);
     38         if (!str.empty()) buf.push_back(N(str));
     39         if (!ifs) break;
     40     }
     41     return buf;
     42 }
     43 
     44 void printMap(const Data &robots, const Vec2 &mapSize) {
     45     for (int y=0; y<mapSize.y; ++y) {
     46         for (int x=0; x<mapSize.x; ++x) {
     47             if (std::count_if(robots.begin(), robots.end(), [&x, &y](const Robot &r) {return r.p.x==x&&r.p.y==y;})>0) {
     48                 std::printf("+");
     49             } else std::printf(".");
     50         }
     51         std::printf("\n");
     52     }
     53     std::printf("\n");
     54 }
     55 
     56 int countRobots(const Data &robots, const Vec2 &from, const Vec2 &to) {
     57     return std::count_if(robots.begin(), robots.end(), [&from, &to](const Robot &r) {
     58         return (r.p.x>=from.x && r.p.y<=from.y && r.p.x<=to.x && r.p.y>=to.y);
     59     });
     60 }
     61 
     62 void moveRobots(Data &robots, const Vec2 &mapSize, int seconds) {
     63     for (auto &r:robots) {
     64         r.p.x += r.v.x*seconds;
     65         r.p.y += r.v.y*seconds;
     66         r.p.x %= mapSize.x;
     67         r.p.y %= mapSize.y;
     68         if (r.p.x<0) r.p.x += mapSize.x;
     69         if (r.p.y<0) r.p.y += mapSize.y;
     70     }
     71 }
     72 
     73 int64_t part1(Data input, Vec2 mapSize) {
     74     int64_t out = 1;
     75     moveRobots(input, mapSize, 100);
     76 
     77     out *= countRobots(input, Vec2(0, mapSize.y/2-1), Vec2(mapSize.x/2-1, 0));
     78     out *= countRobots(input, Vec2(mapSize.x/2+1, mapSize.y/2-1), Vec2(mapSize.x-1, 0));
     79     out *= countRobots(input, Vec2(0, mapSize.y-1), Vec2(mapSize.x/2-1, mapSize.y/2+1));
     80     out *= countRobots(input, Vec2(mapSize.x/2+1, mapSize.y-1), Vec2(mapSize.x-1, mapSize.y/2+1));
     81 
     82     return out;
     83 }
     84 
     85 int64_t part2(Data &input, Vec2 mapSize) {
     86     using namespace std::chrono_literals;
     87     int i=1;
     88     const int minRobots = mapSize.y*0.12;
     89     for (; i<INT_MAX; ++i) {
     90         moveRobots(input, mapSize, 1);
     91         if (countRobots(input, Vec2(mapSize.x/2, mapSize.y-1), Vec2(mapSize.x/2, 0))>minRobots &&
     92             countRobots(input, Vec2(0, mapSize.y/2), Vec2(mapSize.x-1, mapSize.y/2))>minRobots) {
     93             break;
     94         }
     95     }
     96 
     97     return i;
     98 }
     99 
    100 int main(int argc, char **argv) {
    101     Performance perf;
    102     const std::string fname = argc>1 ? argv[1] : "test1.txt";
    103     std::cout << "AoC 2024 day 14 " << fname << std::endl;
    104     Data input = read_file<Data, Robot>(fname);
    105     Vec2 mapSize = fname.contains("test") ? Vec2(11,7) : Vec2(101,103);
    106     std::cout << "part1: " << part1(input, mapSize) << std::endl;
    107     std::cout << "part2: " << part2(input, mapSize) << std::endl;
    108     printMap(input, mapSize);
    109     return 0;
    110 }