/
day24.cpp
126 lines (119 loc) · 3.22 KB
/
day24.cpp
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#include <compare>
#include <initializer_list>
#include <range/v3/algorithm/count_if.hpp>
#include <range/v3/algorithm/minmax.hpp>
#include <range/v3/all.hpp>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/cartesian_product.hpp>
#include <range/v3/view/transform.hpp>
#include <set>
#include <string>
#include "common.h"
#include "fmt/core.h"
namespace aoc2020 {
namespace {
using namespace std::literals::string_view_literals;
struct Position {
int row = 0;
int col = 0;
auto operator<=>(const Position& other) const = default;
bool move(std::string_view dir) {
if (dir[0] == 'e') {
col++;
return false;
} else if (dir[0] == 'w') {
col--;
return false;
} else if (dir == "se"sv) {
col++;
row++;
return true;
} else if (dir == "sw"sv) {
row++;
return true;
} else if (dir == "nw"sv) {
col--;
row--;
return true;
} else if (dir == "ne"sv) {
row--;
return true;
}
return false;
}
};
struct Solver : AbstractSolver {
std::vector<std::string_view> m_input;
void parse(std::string_view input) override {
m_input = input | ranges::views::split('\n') | to_string_view() |
ranges::to_vector;
}
std::set<Position> solve1() const {
std::set<Position> grid;
for (auto line : m_input) {
Position pos;
bool skip = false;
for (auto s : line | ranges::views::sliding(2) | to_string_view()) {
if (skip) {
skip = false;
continue;
}
skip = pos.move(s);
}
if (!skip) {
pos.move(std::string{line.back()});
}
if (grid.contains(pos)) {
grid.erase(pos);
} else {
grid.insert(pos);
}
}
return grid;
}
void part1(std::ostream& ostr) const override { ostr << solve1().size(); }
void part2(std::ostream& ostr) const override {
std::set<Position> grid = solve1();
for ([[maybe_unused]] int i : ranges::views::iota(0, 100)) {
auto [rowmin, rowmax] =
ranges::minmax(grid | ranges::views::transform(
[](const auto& p) { return p.row; }));
auto [colmin, colmax] =
ranges::minmax(grid | ranges::views::transform(
[](const auto& p) { return p.col; }));
auto grid2 =
ranges::views::cartesian_product(
ranges::views::iota(rowmin - 1, rowmax + 2),
ranges::views::iota(colmin - 1, colmax + 2)) |
ranges::views::transform([](const auto& z) {
auto [row, col] = z;
return Position{.row = row, .col = col};
}) |
ranges::views::filter([&](const Position& pos) {
static std::array neigh = {
std::pair{1, 0}, std::pair{1, 1}, std::pair{0, 1},
std::pair{0, -1}, std::pair{-1, 0}, std::pair{-1, -1}};
int count = ranges::count_if(
neigh | ranges::views::transform([&](const auto& p) {
const auto [drow, dcol] = p;
return Position{.row = pos.row + drow,
.col = pos.col + dcol};
}),
[&](const Position& p) { return grid.contains(p); });
if (grid.contains(pos)) {
return !(count == 0 || count > 2);
} else {
return count == 2;
}
}) |
ranges::to<std::set<Position>>();
grid = std::move(grid2);
}
ostr << grid.size();
}
};
} // namespace
std::unique_ptr<AbstractSolver> AbstractSolver::Create() {
return std::make_unique<Solver>();
}
} // namespace aoc2020