#include #include #include #include #include #include #include #include constexpr char ALIVE_CHAR = '#'; constexpr char DEAD_CHAR = '.'; constexpr int CYCLE_COUNT = 6; enum CellState { ALIVE, DEAD }; using Board = std::map, CellState>; std::vector readInput(const std::string &filename) { std::vector input; std::string line; std::ifstream file(filename); while (std::getline(file, line)) { input.push_back(line); } return input; } Board parseBoard(const std::vector &input) { Board board; int rowCursor = 0; for (auto rowIterator = input.cbegin(); rowIterator != input.cend(); (rowCursor++, ++rowIterator)) { auto &line = *rowIterator; int colCursor = 0; for (auto colIterator = line.cbegin(); colIterator != line.cend(); (colCursor++, ++colIterator)) { CellState state = *colIterator == ALIVE_CHAR ? ALIVE : DEAD; std::tuple position(rowCursor, colCursor, 0); board.emplace(std::move(position), std::move(state)); } } return board; } int getNumAdjacentLiveNeighbors(const Board &board, int row, int col, int depth) { int count = 0; for (int dRow = -1; dRow <= 1; dRow++) { for (int dCol = -1; dCol <= 1; dCol++) { for (int dDepth = -1; dDepth <= 1; dDepth++) { if (dRow == 0 && dCol == 0 && dDepth == 0) { continue; } std::tuple position(row + dRow, col + dCol, depth + dDepth); if (board.find(position) == board.end()) { continue; } count += (board.at(position) == ALIVE); } } } return count; } template std::pair getMinMax(const Board &board) { std::vector, CellState>> alivePositions; std::copy_if( board.cbegin(), board.cend(), std::back_inserter(alivePositions), [](const std::pair, CellState> &item) { return item.second == ALIVE; }); auto elements = std::minmax_element( alivePositions.cbegin(), alivePositions.cend(), [](const std::pair, CellState> &item, const std::pair, CellState> &item2) { return std::get(item.first) < std::get(item2.first); }); int minComponent = std::get(elements.first->first); int maxComponent = std::get(elements.second->first); return std::pair(minComponent, maxComponent); } std::pair, std::tuple> getRangeOnEachAxis(const Board &board) { std::pair rowRange = getMinMax<0>(board); std::pair colRange = getMinMax<1>(board); std::pair depthRange = getMinMax<2>(board); return std::pair, std::tuple>( std::tuple(rowRange.first, colRange.first, depthRange.first), std::tuple(rowRange.second, colRange.second, depthRange.second)); } template Val getOrDefault(const std::map &map, Val defaultValue, Key key) { if (map.find(key) == map.end()) { return defaultValue; } return map.at(key); } void printBoard(const Board &board) { auto ranges = getRangeOnEachAxis(board); for (int depth = std::get<2>(ranges.first); depth <= std::get<2>(ranges.second); depth++) { std::cout << "Depth z=" << depth << std::endl; for (int row = std::get<0>(ranges.first); row <= std::get<0>(ranges.second); row++) { for (int col = std::get<1>(ranges.first); col <= std::get<1>(ranges.second); col++) { std::tuple position(row, col, depth); CellState state = getOrDefault(board, DEAD, position); std::cout << ((state == ALIVE) ? ALIVE_CHAR : DEAD_CHAR); } std::cout << std::endl; } } std::cout << std::endl; } int part1(const std::vector &input) { Board board = parseBoard(input); Board nextBoard = board; for (int i = 0; i < CYCLE_COUNT; i++) { printBoard(board); auto ranges = getRangeOnEachAxis(board); for (int row = std::get<0>(ranges.first) - 1; row <= std::get<0>(ranges.second) + 1; row++) { for (int col = std::get<1>(ranges.first) - 1; col <= std::get<1>(ranges.second) + 1; col++) { for (int depth = std::get<2>(ranges.first) - 1; depth <= std::get<2>(ranges.second) + 1; depth++) { int aliveNeighbors = getNumAdjacentLiveNeighbors(board, row, col, depth); std::tuple position(row, col, depth); CellState state = getOrDefault(board, DEAD, position); if (aliveNeighbors != 2 && aliveNeighbors != 3) { state = DEAD; } else if (state == DEAD && aliveNeighbors == 3) { state = ALIVE; } nextBoard[position] = state; } } } std::swap(nextBoard, board); } return std::count_if(board.cbegin(), board.cend(), [](const std::pair, CellState> &item) { return item.second == ALIVE; }); } int main(int argc, char *argv[]) { if (argc != 2) { std::cerr << argv[0] << " " << std::endl; return 1; } auto input = readInput(argv[1]); std::cout << part1(input) << std::endl; }