202 lines
6.0 KiB
C++
202 lines
6.0 KiB
C++
|
#include <fstream>
|
||
|
#include <iostream>
|
||
|
#include <sstream>
|
||
|
#include <vector>
|
||
|
|
||
|
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<Instruction> getInstructions(const std::string &file_name) {
|
||
|
std::ifstream file(file_name);
|
||
|
std::vector<Instruction> 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<Instruction> &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<bool, Instruction> 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<Instruction> &instructions) {
|
||
|
std::vector<Instruction> cuboids{};
|
||
|
for(auto &instruction : instructions) {
|
||
|
std::vector<Instruction> 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;
|
||
|
}
|