#include #include #include #include #include #include #include constexpr int flash_threshold = 9; constexpr int part1_iterations = 100; using Point = std::pair; class Octopus { public: Octopus(int level) : _level(level) {} void increaseLevel() { _level += 1; if (_level > flash_threshold && _can_explode) { _can_explode = false; _exploded = true; } } void resetIfFlash() { if (_level > flash_threshold) { _level = 0; _can_explode = true; _exploded = false; } } std::string printOctopus() const { if (!_can_explode) { return "\033[93;1m0\033[0m"; } return std::to_string(_level); } bool flashed() const { return !_can_explode; } bool exploded() { if (_exploded) { _exploded = false; return true; } return false; } private: int _level; bool _exploded = false; bool _can_explode = true; }; std::vector> getOctopi(const std::string &file_name) { std::vector> octopi; std::ifstream file(file_name); std::string str; while (std::getline(file, str)) { std::vector line{}; for (auto &c : str) { line.emplace_back(c - '0'); } octopi.push_back(std::move(line)); } return octopi; } std::deque increaseLevels(std::vector> &octopi) { std::deque exploded{}; for (int i = 0; i < octopi.size(); i++) { for (int j = 0; j < octopi[i].size(); j++) { auto &octopus = octopi[i][j]; octopus.increaseLevel(); if (octopus.exploded()) { exploded.emplace_back(i, j); } } } return exploded; } void explodeOctopus(std::vector> &octopi, std::deque &exploded, Point &position) { for (int i = -1; i < 2; i++) { for (int j = -1; j < 2; j++) { if (i == 0 && j == 0) { continue; } auto newI = position.first + i; auto newJ = position.second + j; if (newI < 0 || newI >= octopi.size()) { continue; } if (newJ < 0 || newJ >= octopi[newI].size()) { continue; } auto &octopus = octopi[newI][newJ]; octopus.increaseLevel(); if (octopus.exploded()) { exploded.emplace_back(newI, newJ); } } } } void explodeOctopi(std::vector> &octopi, std::deque &exploded) { while (!exploded.empty()) { auto position = exploded.front(); explodeOctopus(octopi, exploded, position); exploded.pop_front(); } } void printOctopi(std::vector> &octopi) { for (auto &line : octopi) { for (auto &octopus : line) { std::cout << octopus.printOctopus(); } std::cout << std::endl; } } uint64_t getFlashesAndReset(std::vector> &octopi) { uint64_t flashes = 0; for (auto &line : octopi) { for (auto &octopus : line) { if (octopus.flashed()) { flashes++; octopus.resetIfFlash(); } } } return flashes; } uint64_t part1(std::vector> &octopi) { uint64_t flashes = 0; for (int i = 0; i < part1_iterations; i++) { auto exploded = increaseLevels(octopi); explodeOctopi(octopi, exploded); flashes += getFlashesAndReset(octopi); } return flashes; } uint64_t part2(std::vector> &octopi) { uint64_t round = part1_iterations; uint64_t flashes = 0; while (flashes != octopi.size() * octopi[0].size()) { auto exploded = increaseLevels(octopi); explodeOctopi(octopi, exploded); flashes = getFlashesAndReset(octopi); round++; } return round; } int main(int argc, char **argv) { if (argc < 2) { std::cerr << "You must provide input file!" << std::endl; return 1; } auto octopi = getOctopi(argv[1]); std::cout << "The octopi flashed \033[91;1m" << part1(octopi) << "\033[0m times." << std::endl; std::cout << "The octopi syncronize on round \033[91;1m" << part2(octopi) << "\033[0m." << std::endl; return 0; }