Files
AdventOfCode/src/2021/Day22.cpp
T
2025-11-30 16:30:12 +01:00

139 lines
3.5 KiB
C++

#include "common/aoc.h"
namespace y2021::day22
{
struct Overlap;
struct Volume
{
int sign = 0;
Index3D min = Index3D{0, 0};
Index3D max = Index3D{0, 0};
Volume()
{
}
Volume(int sign, const Index3D& min, const Index3D& max)
: sign{sign},
min{min},
max{max}
{
}
int64_t GetCubes() const
{
return ((int64_t)max.x - (int64_t)min.x + 1ll) * ((int64_t)max.y - (int64_t)min.y + 1ll) *
((int64_t)max.z - (int64_t)min.z + 1ll);
}
Overlap GetOverlap(const Volume& other) const;
friend std::ostream& operator<<(std::ostream& stream, const Volume& volume)
{
return stream << volume.min << " " << volume.max;
}
};
struct Overlap
{
bool overlap = false;
Volume volume;
Overlap(bool overlap, const Volume& volume)
: overlap{overlap},
volume{volume}
{
}
operator bool()
{
return overlap;
}
};
Overlap Volume::GetOverlap(const Volume& other) const
{
if (min.x > other.max.x || min.y > other.max.y || min.z > other.max.z || max.x < other.min.x ||
max.y < other.min.y || max.z < other.min.z)
return Overlap{false, Volume{0, Index3D{}, Index3D{}}};
return Overlap{
true,
Volume{-other.sign,
Index3D{std::max(min.x, other.min.x), std::max(min.y, other.min.y), std::max(min.z, other.min.z)},
Index3D{std::min(max.x, other.max.x), std::min(max.y, other.max.y), std::min(max.z, other.max.z)}}};
}
REGISTER_DAY(2021, Day22, std::vector<Volume>, int64_t);
REGISTER_TEST_EXAMPLE(2021, Day22, ExampleInput, 1, 474140);
REGISTER_TEST(2021, Day22, Input, 1, 596598);
REGISTER_TEST_EXAMPLE(2021, Day22, ExampleInput, 2, 2758514936282235);
REGISTER_TEST(2021, Day22, Input, 2, 1199121349148621);
READ_INPUT(input)
{
std::vector<Volume> volumes;
std::string str;
while (getline(input, str))
{
Volume volume;
std::stringstream ss{str};
std::string s;
ss >> s >> "x=" >> volume.min.x >> ".." >> volume.max.x >> "," >> "y=" >> volume.min.y >> ".." >> volume.max.y >>
"," >> "z=" >> volume.min.z >> ".." >> volume.max.z;
volume.sign = s == "on" ? 1 : -1;
volumes.emplace_back(volume);
}
return volumes;
}
OUTPUT1(input)
{
Array3D<char> values{101, 101, 101};
values.Fill('.');
for (auto& region : input)
{
for (int z = std::max(region.min.z, -50); z <= std::min(region.max.z, 50); z++)
{
for (int y = std::max(region.min.y, -50); y <= std::min(region.max.y, 50); y++)
{
for (int x = std::max(region.min.x, -50); x <= std::min(region.max.x, 50); x++)
{
if (values.IsInside(Index3D{x + 50, y + 50, z + 50}))
{
values.Set(x + 50, y + 50, z + 50, region.sign > 0 ? '#' : '.');
}
}
}
}
}
return values.Count('#');
}
OUTPUT2(input)
{
std::vector<Volume> volumes;
for (auto& volume : input)
{
size_t size = volumes.size();
for (size_t i = 0; i < size; i++)
{
Overlap overlap = volume.GetOverlap(volumes[i]);
if (overlap)
{
volumes.emplace_back(overlap.volume);
}
}
if (volume.sign > 0)
{
volumes.emplace_back(volume);
}
}
return Helper::Sum<int64_t>(volumes,
[](int64_t sum, const Volume& vol) { return sum + vol.GetCubes() * vol.sign; });
}
}