aoc25/day4/main.cpp
2025-12-06 20:36:52 +00:00

165 lines
5 KiB
C++

#include <array>
#include <cstddef>
#include <expected>
#include <fstream>
#include <iostream>
#include <mdspan>
#include <print>
#include <ranges>
#include <string>
#include <vector>
struct Diagram {
std::vector<int> data;
size_t width;
size_t height;
using GridView = std::mdspan<int, std::dextents<size_t, 2>>;
auto grid() { return GridView(data.data(), height, width); }
};
auto printMap(Diagram &diagram) {
auto grid = diagram.grid();
for (auto row = 0UZ; row != grid.extent(0); row++) {
for (auto col = 0UZ; col != grid.extent(1); col++) {
std::print("{}", grid[row, col]);
}
std::println();
}
// std::println("Map: {}", diagram.data);
std::println("Width: {}", diagram.width);
std::println("Height: {}", diagram.height);
}
auto parseMap(const std::string &filename) -> std::expected<Diagram, std::string> {
std::ifstream inputF{filename};
if (!inputF) {
return std::unexpected{"Some file open error.\n"};
}
Diagram diagram{};
std::string puzzleLine{};
while (std::getline(inputF, puzzleLine)) {
// std::println("{:3}: {}", diagram.height, puzzleLine);
diagram.data.push_back(0);
diagram.data.append_range(puzzleLine | std::views::transform([](char c) -> int { return c == '.' ? 0 : 1; }));
diagram.data.push_back(0);
diagram.height++;
// ugly
diagram.width = puzzleLine.length() + 2;
}
// also ugly, bound it with 0s
diagram.data.append_range(std::vector<int>(diagram.width, 0));
diagram.data.insert_range(diagram.data.begin(), std::vector<int>(diagram.width, 0));
diagram.height += 2;
// printMap(diagram);
// auto ms2 = std::mdspan(diagram.data.data(), diagram.width, diagram.height);
return std::move(diagram);
}
auto countMovablePaper(Diagram &diagram) -> long {
long nMovablePaper{};
auto grid = diagram.grid();
for (auto row = 1UZ; row != grid.extent(0) - 1; row++) {
for (auto col = 1UZ; col != grid.extent(1) - 1; col++) {
if (grid[row, col] == 1) {
// std::print("checking [{},{}]:", row, col);
// shitty kernel
int upLeft = grid[row - 1, col - 1];
int up = grid[row - 1, col];
int upRight = grid[row - 1, col + 1];
int left = grid[row, col - 1];
int right = grid[row, col + 1];
int downLeft = grid[row + 1, col - 1];
int down = grid[row + 1, col];
int downRight = grid[row + 1, col + 1];
// caveman shit
if ((upLeft + up + upRight + left + right + downLeft + down + downRight) < 4) {
// std::println("Found");
nMovablePaper++;
}
}
// std::println();
}
}
return nMovablePaper;
}
auto moveMoveablePaper(Diagram &diagram) -> long {
long totalPaperRemoved{};
auto grid = diagram.grid();
constexpr std::array<std::pair<int, int>, 8> offsets = {
{{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}};
while (true) {
long currentPaperRemoved = 0;
for (auto row = 1UZ; row != grid.extent(0) - 1; row++) {
for (auto col = 1UZ; col != grid.extent(1) - 1; col++) {
if (grid[row, col] != 1) {
continue;
}
// std::print("checking [{},{}]:", row, col);
// shitty kernal
int neighbors{0};
for (auto [dr, dc] : offsets) {
// mdspan allows [x, y] indexing natively
neighbors += grid[row + dr, col + dc];
}
if (neighbors < 4) {
grid[row, col] = 0;
// std::println("Found");
currentPaperRemoved++;
}
}
// std::println();
}
if (currentPaperRemoved == 0) {
std::println("Didn't remove any more paper this iteration! Stopping.");
break;
}
totalPaperRemoved += currentPaperRemoved;
// printMap(diagram);
}
return totalPaperRemoved;
}
auto main() -> int {
auto testCase = parseMap("test_input");
if (testCase) {
// auto testResult = countMovablePaper(*testCase);
// std::println("P1 Testcase result: {}", testResult);
auto testResultP2 = moveMoveablePaper(*testCase);
std::println("P2 Testcase result: {}", testResultP2);
} else {
std::print("{}\n", testCase.error());
}
auto realPuzzle = parseMap("puzzle_input");
if (realPuzzle) {
// auto realResult = countMovablePaper(*realPuzzle);
// std::println("P1 Real result: {}", realResult);
auto realResultP2 = moveMoveablePaper(*realPuzzle);
std::println("P2 Real result: {}", realResultP2);
} else {
std::print("{}\n", realPuzzle.error());
}
return 0;
}