main.cpp (5450B)
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 <expected> 10 #include <set> 11 #include "utils.hpp" 12 13 typedef std::vector<std::string> Data; 14 typedef std::pair<int, int> Vec2; 15 16 static const std::vector<Vec2> sDirs = {Vec2(0, -1), Vec2(1, 0), Vec2(0, 1), Vec2(-1, 0)}; 17 18 19 class Plot : public std::set<Vec2> { 20 public: 21 bool has(const Vec2 &p) const { 22 return this->count(p)>0; 23 //std::count(this->begin(), this->end(), p)>0; 24 } 25 26 bool addNeighbors(const Data &input, char c) { 27 const int sz = input.size(); 28 bool inserted = false; 29 Plot cp(*this); 30 for (const Vec2 &p : cp) { 31 for (const Vec2 &dir:sDirs) { 32 Vec2 pd(p.first+dir.first, p.second+dir.second); 33 if (pd.first>=0&&pd.first<sz&&pd.second>=0&&pd.second<sz) { 34 if (input[pd.second][pd.first]==c&&!cp.has(pd)) { 35 this->insert(pd); 36 inserted = true; 37 } 38 } 39 } 40 } 41 return inserted; 42 } 43 44 int64_t area() const { return this->size(); } 45 46 int64_t perimeter() const { 47 int64_t per = 0; 48 for (const auto &p : *this) { 49 int64_t cnt = 4; 50 for (const Vec2 &dir:sDirs) { 51 Vec2 pd(p.first+dir.first, p.second+dir.second); 52 if (this->has(pd)) { 53 cnt--; 54 //std::printf("[%d,%d] has neighbor [%d,%d]\n", p.first, p.second, pd.first, pd.second); 55 } 56 } 57 //std::printf("(%ld)\n", cnt); 58 per+=cnt; 59 } 60 return per; 61 } 62 63 int64_t sides() const { 64 int64_t cnt = 0; 65 std::vector<Vec2> n,e,s,w; 66 for (const auto &p : *this) { 67 if (!this->has(Vec2(p.first+1, p.second))) e.push_back(p); 68 if (!this->has(Vec2(p.first-1, p.second))) w.push_back(p); 69 if (!this->has(Vec2(p.first, p.second+1))) s.push_back(p); 70 if (!this->has(Vec2(p.first, p.second-1))) n.push_back(p); 71 } 72 std::sort(n.begin(), n.end(), [](auto &p1, auto &p2){ return p1.second<p2.second/* && p1.first<p2.first*/; }); 73 std::sort(s.begin(), s.end(), [](auto &p1, auto &p2){ return p1.second<p2.second; }); 74 std::sort(e.begin(), e.end(), [](auto &p1, auto &p2){ return p1.first<p2.first; }); 75 std::sort(w.begin(), w.end(), [](auto &p1, auto &p2){ return p1.first<p2.first; }); 76 77 std::printf("east:"); 78 for (auto &p:e) { 79 std::printf("[%d,%d]", p.first, p.second); 80 } 81 std::printf("\n"); 82 83 int v=-1; 84 int prev=-1; 85 for (auto &p : n) { 86 if (p.second!=v || std::abs(prev-p.first)>1) { cnt++; } 87 v=p.second; 88 prev=p.first; 89 } 90 v=-1; 91 prev=-1; 92 for (auto &p : s) { 93 if (p.second!=v || std::abs(prev-p.first)>1) cnt++; 94 v=p.second; 95 prev=p.first; 96 } 97 v=-1; 98 prev=-1; 99 for (auto &p : e) { 100 if (p.first!=v || std::abs(prev-p.second)>1) cnt++; 101 v=p.first; 102 prev=p.second; 103 } 104 std::printf("north+south+east count:%ld\n", cnt); 105 v=-1; 106 prev=-1; 107 for (auto &p : w) { 108 if (p.first!=v || std::abs(prev-p.second)>1) cnt++; 109 v=p.first; 110 prev=p.second; 111 } 112 return cnt; 113 } 114 115 void print() const { 116 for (auto &p : *this) { 117 std::printf("[%d,%d]", p.first, p.second); 118 } 119 } 120 }; 121 // 1046941 too high 122 // 918855 too high 123 template<typename T> 124 T read_file(const std::string &path) { 125 std::ifstream ifs(path, std::ios::binary); 126 if (!ifs.is_open()) { 127 throw std::runtime_error(path+":"+std::strerror(errno)); 128 } 129 T buf; 130 while (1) { 131 std::string str; 132 std::getline(ifs, str); 133 if (!str.empty()) buf.push_back(str); 134 if (!ifs) break; 135 } 136 return buf; 137 } 138 139 Plot findPlot(const Data &input [[ maybe_unused ]], Vec2 start [[ maybe_unused ]]) { 140 Plot plot; 141 char c = input[start.second][start.first]; 142 plot.insert(start); 143 while (plot.addNeighbors(input, c)) {} 144 return plot; 145 } 146 147 std::pair<int64_t, int64_t> solve(Data &input [[ maybe_unused ]]) { 148 int64_t p1sum = 0; 149 int64_t p2sum = 0; 150 // square maps only! 151 Plot processed; 152 for (int y=0; y<(int)input.size(); ++y) { 153 for (int x=0; x<(int)input[y].size(); ++x) { 154 if (!processed.has(Vec2(x, y))) { 155 Plot p = findPlot(input, Vec2(x,y)); 156 processed.insert(p.begin(), p.end()); 157 std::printf("\n-------------\nfound plot (%c):\n", input[y][x]); 158 p.print(); 159 std::printf("\nsides: %ld\n", p.sides()); 160 p1sum += p.area() * p.perimeter(); 161 p2sum += p.area() * p.sides(); 162 } 163 } 164 } 165 166 return std::make_pair(p1sum, p2sum); 167 } 168 169 int main(int argc, char **argv) { 170 Performance perf; 171 const std::string fname = argc>1 ? argv[1] : "test1.txt"; 172 std::cout << "AoC 2024 day 12 " << fname << std::endl; 173 Data input = read_file<Data>(fname); 174 auto [p1, p2] = solve(input); 175 std::cout << "part1: " << p1 << std::endl; 176 std::cout << "part2: " << p2 << std::endl; 177 178 return 0; 179 }