advent2024

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

main.cpp (4633B)


      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 <deque>
     10 #include <iterator>
     11 #include <chrono>
     12 #include "utils.hpp"
     13 
     14 enum class SlotType {
     15     file,
     16     space
     17 };
     18 
     19 class Slot {
     20 public:
     21     SlotType type;
     22     int len;
     23     int id;
     24     bool moved = false;
     25 
     26     Slot(SlotType _type, int _len, int _id=-1):type(_type),len(_len),id(_id) {}
     27 
     28     bool isSpace() const { return type==SlotType::space; }
     29     bool isFile() const { return type==SlotType::file; }
     30 };
     31 
     32 typedef std::vector<Slot> Data;
     33 
     34 template<typename T>
     35 T read_file(const std::string &path) {
     36     std::ifstream ifs(path, std::ios::binary);
     37     if (!ifs.is_open()) {
     38         throw std::runtime_error(path+":"+std::strerror(errno));
     39     }
     40     std::uintmax_t size = std::filesystem::file_size(path);
     41     std::vector<char> buf(size);
     42     if (!ifs.read((char *)buf.data(), buf.size())) {
     43         throw std::runtime_error(path+":"+std::strerror(errno));
     44     }
     45     T out;
     46     int id=0;
     47     for (int i=0; i<(int)buf.size(); ++i) {
     48         char c = buf[i];
     49         if (c-'0'>=0) {
     50             if (i%2==1) {
     51                 out.push_back(Slot(SlotType::space, c-'0'));
     52             } else {
     53                 out.push_back(Slot(SlotType::file, c-'0', id++));
     54             }
     55         }
     56     }
     57     return out;
     58 }
     59 
     60 bool checkEmptySpaces(const Data &input) {
     61     for (auto it=input.rbegin(); it!=input.rend(); ++it) {
     62         if (it->isSpace() && it->len>0) return true;
     63     }
     64     return false;
     65 }
     66 
     67 void cleanEmptySpaces(Data &input) {
     68     for (auto it=input.begin(); it!=input.end();) {
     69         if (it->isSpace() && it->len==0) {
     70             it = input.erase(it);
     71         } else {
     72             it++;
     73         }
     74     }
     75 }
     76 
     77 void trimSpace(Data &input) {
     78     if (input.back().isSpace()) {
     79         //std::printf("trimSpace()\n");
     80         input.pop_back();
     81     }
     82 }
     83 
     84 void printInput(const Data &input) {
     85     for (auto &s:input) {
     86         if (s.isSpace()){
     87             std::printf("[ :%d]", s.len);
     88         } else {
     89             std::printf("[%d:%d]", s.id, s.len);
     90         }
     91     }
     92     std::cout << std::endl;
     93 }
     94 
     95 int64_t checksum(const Data &input) {
     96     int64_t sum = 0;
     97     int64_t i = 0;
     98     for (auto s:input) {
     99         int64_t im = i+s.len;
    100         for (; i<im; ++i) {
    101             if (s.isFile()) sum+=(s.id*i);
    102         }
    103     }
    104     return sum;
    105 }
    106 
    107 void mergeSpaces(Data &input) {
    108     for (auto its=input.begin(); its!=input.end();) {
    109         auto itn = std::next(its, 1);
    110         if (its->isSpace() && itn!=input.end() && itn->isSpace()) {
    111             its->len += itn->len;
    112             its = input.erase(itn);
    113         } else its++;
    114     }
    115 
    116 }
    117 
    118 int64_t part1(Data input) {
    119     while (checkEmptySpaces(input)) {
    120         trimSpace(input);
    121         for (auto it=input.begin(); it!=input.end(); ++it) {
    122             if (it->isSpace()&&it->len>0) {
    123                 if (it->len>=input.back().len) {
    124                     auto tr = input.insert(it, input.back());
    125                     it = std::next(tr, 1);
    126                     it->len -= tr->len;
    127                     input.pop_back();
    128                 } else {
    129                     auto tr = input.insert(std::next(it, 1), input.back());
    130                     it = std::prev(tr, 1);
    131                     input.back().len -= it->len;
    132                     tr->len = it->len;
    133                     it->len = 0;
    134                 }
    135                 break;
    136             }
    137         }
    138         cleanEmptySpaces(input);
    139     }
    140     cleanEmptySpaces(input);
    141     return checksum(input);
    142 }
    143 
    144 int64_t part2(Data input) {
    145     for (auto itf=input.rbegin(); itf!=input.rend(); itf=std::find_if(input.rbegin(), input.rend(), [](auto s){ return s.isFile()&&!s.moved; }))
    146     {
    147         auto its = std::find_if(input.begin(), input.end(), [&itf](auto s){
    148             return s.isSpace() && s.len>=itf->len;
    149         });
    150         if (its!=input.end()&&std::distance(its, itf.base())>0) {
    151             Slot fc = *itf;
    152             itf->type = SlotType::space;
    153             itf->id = -1;
    154             its->len -= itf->len;
    155             auto tr = input.insert(its, fc);
    156             tr->moved = true;
    157         } else {
    158             itf->moved = true;
    159         }
    160         cleanEmptySpaces(input);
    161         mergeSpaces(input);
    162     }
    163 
    164     return checksum(input);
    165 }
    166 
    167 int main(int argc, char **argv) {
    168     Performance perf;
    169     const std::string fname = argc>1 ? argv[1] : "test1.txt";
    170     std::cout << "AoC 2024 day 09 " << fname << std::endl;
    171     Data input = read_file<Data>(fname);
    172     std::cout << "part1: " << part1(input) << std::endl;
    173     std::cout << "part2: " << part2(input) << std::endl;
    174 
    175     return 0;
    176 }