advent_of_code_2021/22/main.cpp
2022-12-03 20:21:21 +01:00

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;
}