Files
advent-of-code/2022/puzzle-18-01.cc

116 lines
2.8 KiB
C++

//
// Created by Matthew Gretton-Dann on 16/12/2022.
//
#include <cassert>
#include <array>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <regex>
#include <set>
#include <stdexcept>
#include <utility>
#include <vector>
using Int = std::int64_t;
using UInt = std::uint64_t;
using Point3 = std::tuple<UInt, UInt, UInt>;
using namespace std::string_literals;
struct Grid3
{
explicit Grid3(std::size_t size)
: size_(size) { map_.resize(size * size * size, false); }
auto point(Point3 const& p) const noexcept -> bool
{
assert(std::get<0>(p) < size_);
assert(std::get<1>(p) < size_);
assert(std::get<2>(p) < size_);
return map_[std::get<0>(p) * size_ * size_ + std::get<1>(p) * size_ + std::get<2>(p)];
}
void point(Point3 const& p, bool v)
{
assert(std::get<0>(p) < size_);
assert(std::get<1>(p) < size_);
assert(std::get<2>(p) < size_);
map_[std::get<0>(p) * size_ * size_ + std::get<1>(p) * size_ + std::get<2>(p)] = v;
}
std::size_t size_;
std::vector<bool> map_;
};
auto main() -> int
{
std::string line;
std::vector<Point3> points;
UInt max{0};
std::regex const re{"(\\d+),(\\d+),(\\d+)"};
while (std::getline(std::cin, line)) {
std::smatch m;
if (!std::regex_search(line, m, re)) {
std::cerr << "Cannot interpret: " << line << "\n";
return EXIT_FAILURE;
}
Point3 pt{std::make_tuple(std::stoull(m.str(1)), std::stoull(m.str(2)), std::stoull(m.str(3)))};
max = std::max(std::get<0>(pt), max);
max = std::max(std::get<1>(pt), max);
max = std::max(std::get<2>(pt), max);
points.push_back(pt);
}
Grid3 grid(max + 2);
for (auto const& pt : points) {
grid.point(pt, true);
}
UInt exposed_sides{0};
for (auto const& pt : points) {
UInt x{std::get<0>(pt)};
UInt y{std::get<1>(pt)};
UInt z{std::get<2>(pt)};
if (x > 0) {
exposed_sides += grid.point(std::make_tuple(x - 1, y, z)) ? 0 : 1;
}
else {
++exposed_sides;
}
exposed_sides += grid.point(std::make_tuple(x + 1, y, z)) ? 0 : 1;
if (y > 0) {
exposed_sides += grid.point(std::make_tuple(x, y - 1, z)) ? 0 : 1;
}
else {
++exposed_sides;
}
exposed_sides += grid.point(std::make_tuple(x, y + 1, z)) ? 0 : 1;
if (z > 0) {
exposed_sides += grid.point(std::make_tuple(x, y, z - 1)) ? 0 : 1;
}
else {
++exposed_sides;
}
exposed_sides += grid.point(std::make_tuple(x, y, z + 1)) ? 0 : 1;
}
std::cout << "Surface area: " << exposed_sides << "\n";
#if 0
for (UInt z{0}; z <= max; ++z) {
std::cout << "\nz = " << z << "\n";
for (UInt y{0}; y <= max; ++y) {
for (UInt x{0}; x <= max; ++x) {
std::cout << (grid.point(std::make_tuple(x, y, z)) ? '#' : ' ');
}
std::cout << "\n";
}
}
#endif
return EXIT_SUCCESS;
}