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 }