#include #include #include #include using Dish = std::vector; using History = std::vector>; constexpr int CYCLES = 1'000'000'000; Dish parse(const char* file) { Dish v; if (std::ifstream input{ file }; input.is_open()) { std::string line; while (not std::getline(input,line).eof()) { v.push_back(std::move(line)); } } return v; } std::vector encode(const Dish& v) { auto len = v.size(); std::vector e(len * len, 0); for (int x = 0; x < len; ++x) { for (int y = 0; y < len; ++y) { e[x * len + y] = v[x][y] == 'O'; } } return e; } Dish& tilt_north(Dish& v) { for (int c = 0; c < v.size(); ++c) { int floor{}; for (int r = floor; r < v.size(); ++r) { switch (v[r][c]) { case '#': floor = r + 1; break; case 'O': v[r][c] = '.'; v[floor++][c] = 'O'; } } } return v; } Dish& tilt_south(Dish& v) { for (int c = 0; c < v.size(); ++c) { int floor{ static_cast(v.size() - 1) }; for (int r = floor; r >= 0; --r) { switch (v[r][c]) { case '#': floor = r - 1; break; case 'O': v[r][c] = '.'; v[floor--][c] = 'O'; } } } return v; } Dish& tilt_west(Dish& v) { for (int r = 0; r < v.size(); ++r) { int floor{}; for (int c = floor; c < v.size(); ++c) { switch (v[r][c]) { case '#': floor = c + 1; break; case 'O': v[r][c] = '.'; v[r][floor++] = 'O'; } } } return v; } Dish& tilt_east(Dish& v) { for (int r = 0; r < v.size(); ++r) { int floor{ static_cast(v.size() - 1) }; for (int c = floor; c >= 0; --c) { switch (v[r][c]) { case '#': floor = c - 1; break; case 'O': v[r][c] = '.'; v[r][floor--] = 'O'; } } } return v; } Dish& cycle(Dish& v) { return tilt_east(tilt_south(tilt_west(tilt_north(v)))); } int load(const std::vector& v, int l) { int load{}; for (int x = 0; x < l; ++x) { for (int y = 0; y < l; ++y) { load += (l - x) * v[x * l + y]; } } return load; } int dup(History& hist, Dish dish) { auto h = encode(dish); if (auto found = std::find(hist.cbegin(), hist.cend(), h); found != hist.cend()) { return hist.cend() - found; } hist.push_back(std::move(h)); return 0; } int main(int argc, char* argv[]) { auto v = parse(argv[1]); History history; history.push_back(encode(v)); int p, np; for (p = 0; p == 0; p = dup(history, cycle(v))); np = history.size() - p; std::cout << load(history[np + (CYCLES - np) % p], v.size()) << std::endl; return 0; }