#include namespace views = std::views; namespace ranges = std::ranges; void pad_grid(std::vector& input) { for (size_t i = 0; i < input.size(); ++i) { input[i] = "." + input[i] + "."; } int const row_size = input[0].size(); input.emplace(input.begin(), row_size, '.'); input.emplace_back(row_size, '.'); } auto parse_input(std::istream& is) { const std::string input = { std::istreambuf_iterator(is), std::istreambuf_iterator() }; auto lines = views::split(input, '\n') | views::filter([](auto&& line) { return not line.empty(); }) | ranges::to>(); pad_grid(lines); return lines; } constexpr std::array tuple_to_array(std::tuple&& t) { return {std::get<0>(t), std::get<1>(t), std::get<2>(t)}; } auto next_state(std::vector const& input) { int nremoved = 0; auto forklift_pass = [&nremoved](auto&& columns) -> char { if (columns[1][1] == '@' and ranges::count(columns | views::join, '@') < 5) { ++nremoved; return '.'; } return columns[1][1]; }; std::vector next_state; for (auto const& rows : input | views::slide(3)) { next_state.push_back( views::zip(rows[0], rows[1], rows[2]) | views::transform(tuple_to_array) | views::slide(3) | views::transform(forklift_pass) | ranges::to()); } pad_grid(next_state); return std::make_tuple(next_state, nremoved); } void part1(auto input) { auto const [_, answer] = next_state(input); std::println("{}", answer); } void part2(auto input) { // Write second part solution here int answer = 0; while (true) { auto const [_next_state, increment] = next_state(input); if (increment == 0) { break; } input = _next_state; answer += increment; } std::println("{}", answer); } int main() { auto input = parse_input(std::cin); part1(input); part2(input); return 0; }