summaryrefslogtreecommitdiffstats
path: root/day04/solution.cpp
blob: 48afb58d6cf4d3691a27a3b46dab5fab597b7da5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <bits/stdc++.h>

namespace views = std::views;
namespace ranges = std::ranges;

void pad_grid(std::vector<std::string>& 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<char>(is),
        std::istreambuf_iterator<char>()
    };

    auto lines = views::split(input, '\n')
        | views::filter([](auto&& line) { return not line.empty(); })
        | ranges::to<std::vector<std::string>>();

    pad_grid(lines);
    return lines;
}

constexpr std::array<char, 3> tuple_to_array(std::tuple<char, char, char>&& t) {
    return {std::get<0>(t), std::get<1>(t), std::get<2>(t)};
}

auto next_state(std::vector<std::string> 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<std::string> 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<std::string>());
    }
    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;
}