#include #include #include #include class Instruction { public: Instruction() {}; void setXMin(int64_t x) { x_min = x; } void setXMax(int64_t x) { x_max = x; } void setYMin(int64_t y) { y_min = y; } void setYMax(int64_t y) { y_max = y; } void setZMin(int64_t z) { z_min = z; } void setZMax(int64_t z) { z_max = z; } int64_t getXMin() const { return x_min; } int64_t getXMax() const { return x_max; } int64_t getYMin() const { return y_min; } int64_t getYMax() const { return y_max; } int64_t getZMin() const { return z_min; } int64_t getZMax() const { return z_max; } void setState(bool on) { state = on; } bool getState() const { return state; } uint64_t getArea() const { return (abs(x_max - x_min) + 1) * (abs(y_max - y_min) + 1) * (abs(z_max - z_min) + 1); } void print() const { std::cout << "CUB: X=" << getXMin() << ".." << getXMax() << ", Y=" << getYMin() << ".." << getYMax() << ", Z=" << getZMin() << ".." << getZMax() << "; " << (getState() ? "LIT" : "DARK") << std::endl; } private: int64_t x_min = 0; int64_t x_max = 0; int64_t y_min = 0; int64_t y_max = 0; int64_t z_min = 0; int64_t z_max = 0; bool state = false; }; std::vector getInstructions(const std::string &file_name) { std::ifstream file(file_name); std::vector result{}; int64_t tmp_i = 0; std::string tmp_s = ""; char tmp_c = ' '; std::string str; while (std::getline(file, str)) { result.emplace_back(); if(str[1] == 'n') { result.back().setState(true); } else { result.back().setState(false); } std::stringstream ss(str); int64_t numbers[6]; int64_t index = 0; ss >> tmp_s; for(int64_t i = 0; i < 3; i++) { ss >> tmp_c; ss >> tmp_c; ss >> tmp_i; numbers[index] = tmp_i; index++; ss >> tmp_c; ss >> tmp_c; ss >> tmp_i; numbers[index] = tmp_i; index++; ss >> tmp_c; } result.back().setXMin(numbers[0]); result.back().setXMax(numbers[1]); result.back().setYMin(numbers[2]); result.back().setYMax(numbers[3]); result.back().setZMin(numbers[4]); result.back().setZMax(numbers[5]); } return result; } int64_t part1(const std::vector &instructions) { bool cubes[101][101][101]; for(int64_t x = 0; x < 101; x++) { for(int64_t y = 0; y < 101; y++) { for(int64_t z = 0; z < 101; z++) { cubes[x][y][z] = false; } } } for(auto &instruction : instructions) { for(int64_t x = instruction.getXMin() + 50; x <= instruction.getXMax() + 50; x++) { for(int64_t y = instruction.getYMin() + 50; y <= instruction.getYMax() + 50; y++) { for(int64_t z = instruction.getZMin() + 50; z <= instruction.getZMax() + 50; z++) { if(x < 0 || x > 100 || y < 0 || y > 100 || z < 0 || z > 100) { continue; } cubes[x][y][z] = instruction.getState(); } } } } int64_t lit = 0; for(int64_t x = 0; x < 101; x++) { for(int64_t y = 0; y < 101; y++) { for(int64_t z = 0; z < 101; z++) { if(cubes[x][y][z]) { lit++; } } } } return lit; } std::pair getOverlappingCube(Instruction cube1, Instruction cube2) { if(cube2.getXMax() < cube1.getXMin() || cube2.getXMin() > cube1.getXMax() || cube2.getYMax() < cube1.getYMin() || cube2.getYMin() > cube1.getYMax() || cube2.getZMax() < cube1.getZMin() || cube2.getZMin() > cube1.getZMax()) { return {false, Instruction()}; } auto x_min = cube1.getXMin() > cube2.getXMin() ? cube1.getXMin() : cube2.getXMin(); auto x_max = cube1.getXMax() < cube2.getXMax() ? cube1.getXMax() : cube2.getXMax(); auto y_min = cube1.getYMin() > cube2.getYMin() ? cube1.getYMin() : cube2.getYMin(); auto y_max = cube1.getYMax() < cube2.getYMax() ? cube1.getYMax() : cube2.getYMax(); auto z_min = cube1.getZMin() > cube2.getZMin() ? cube1.getZMin() : cube2.getZMin(); auto z_max = cube1.getZMax() < cube2.getZMax() ? cube1.getZMax() : cube2.getZMax(); auto res = Instruction(); res.setXMin(x_min); res.setXMax(x_max); res.setYMin(y_min); res.setYMax(y_max); res.setZMin(z_min); res.setZMax(z_max); return {true, res}; } uint64_t part2(const std::vector &instructions) { std::vector cuboids{}; for(auto &instruction : instructions) { std::vector new_cuboids{}; for(auto cuboid : cuboids) { auto intersect = getOverlappingCube(cuboid, instruction); if(!intersect.first) { continue; } intersect.second.setState(!cuboid.getState()); new_cuboids.push_back(intersect.second); } for(auto &cuboid : new_cuboids) { cuboids.push_back(cuboid); } if(instruction.getState()) { cuboids.push_back(instruction); } } uint64_t lit = 0; for(auto &cuboid : cuboids) { lit += cuboid.getArea() * (cuboid.getState() ? 1 : -1); } return lit; } int main(int argc, char **argv) { if (argc < 2) { std::cerr << "You must provide input file!" << std::endl; return 1; } auto instructions = getInstructions(argv[1]); std::cout << "There are \033[91;1m" << part1(instructions) << "\033[0m cubes lit." << std::endl; std::cout << "There are \033[91;1m" << part2(instructions) << "\033[0m cubes lit." << std::endl; return 0; }