Skip to content

Commit c3cb65c

Browse files
committed
Optimize.
1 parent d15cc28 commit c3cb65c

File tree

1 file changed

+33
-32
lines changed

1 file changed

+33
-32
lines changed

20/solve.cc

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,39 @@
22
namespace {
33

44
using Scalar = int;
5-
using Cost = unsigned short;
5+
using Cost = int;
6+
template <typename T> using Vec = std::vector<T>;
67

78
struct Cell {
8-
static constexpr Cost MAXCOST = std::numeric_limits<Cost>::max() - 1;
9-
static constexpr Cost WALL = std::numeric_limits<Cost>::max();
9+
static constexpr Cost MAXCOST = std::numeric_limits<Cost>::max();
10+
static constexpr Cost WALL = -1; // less than any other cost, so looks visited.
1011
Cost cost;
1112
Cell( char c ) : cost{ c == '#' ? WALL :MAXCOST} {}
12-
bool wall() const { return cost == WALL; }
1313
};
1414

1515
struct Point {
16-
Scalar row{}, col{};
17-
Point operator+ (const Point &rhs) const noexcept { return { Scalar(row + rhs.row), Scalar(col + rhs.col) }; }
16+
Scalar row_, col_;
17+
Point operator+ (const Point &rhs) const noexcept {
18+
return { Scalar(row() + rhs.row()), Scalar(col() + rhs.col()) }; }
1819
auto operator <=> (const Point &) const = default;
19-
unsigned mag() const { return abs(row) + abs(col); }
20+
int mag() const { return abs(row()) + abs(col()); }
21+
Scalar row() const { return row_; }
22+
Scalar col() const { return col_; }
2023
};
2124

2225
enum Direction { NORTH, EAST, SOUTH, WEST };
2326
constexpr Point velocities[] = { {Scalar(-1), 0}, {0, 1}, {1, 0}, {0, Scalar(-1)} };
2427

2528
struct Maze {
26-
std::vector<Cell> cells;
29+
Vec<Cell> cells;
2730
Scalar cols{}, rows{};
2831
Point START, END;
29-
bool contains(Point p) { return p.row >= 0 && p.row < rows && p.col >= 0 && p.col < cols; }
30-
Cell &at(Point p) { return cells[p.row * cols + p.col]; }
31-
const Cell &at(Point p) const { return cells[p.row * cols + p.col]; }
32+
bool contains(Point p) { return p.row() >= 0 && p.row() < rows && p.col() >= 0 && p.col() < cols; }
33+
Cell &at(Point p) { return cells[p.row() * cols + p.col()]; }
34+
const Cell &at(Point p) const { return cells[p.row() * cols + p.col()]; }
3235
// our maze has a single direction, so we just have to find the first
33-
std::vector<Point> pathfind() {
34-
std::vector<Point> path;
36+
template <typename V>
37+
void pathfind(V &path) {
3538
path.push_back(START);
3639
at(START).cost = 0;
3740
for (size_t pos = 0; path[pos] != END; ++pos) {
@@ -42,15 +45,15 @@ struct Maze {
4245
if (!contains(to))
4346
continue;
4447
auto &cell = at(to);
45-
if (cell.wall() || cell.cost <= existing.cost + 1)
48+
if (cell.cost <= existing.cost + 1)
4649
continue;
4750
cell.cost = existing.cost + 1;
4851
path.push_back(to);
4952
}
5053
assert(path.size() > pos);
5154
}
52-
return path;
5355
}
56+
Maze(const Maze &) = delete;
5457
Maze(std::istream &is) noexcept {
5558
cells.reserve(141 * 141);
5659
rows = 0;
@@ -70,31 +73,29 @@ struct Maze {
7073
}
7174
};
7275

73-
void solve(std::istream &is, std::ostream &os, int maxdistance, int threshold) {
76+
template <int maxdistance, int threshold>
77+
void solve(std::istream &is, std::ostream &os) {
7478
Maze maze(is);
75-
std::vector<Point> path = maze.pathfind();
76-
77-
unsigned long total = 0;
78-
79+
Vec<Point> path;
80+
maze.pathfind(path);
81+
int total = 0;
7982
for (const auto &start : path) {
80-
for (int rowdelta = -maxdistance; rowdelta <= maxdistance; ++rowdelta) {
81-
for (int coldelta = -maxdistance + abs(rowdelta); coldelta <= maxdistance - abs(rowdelta); ++coldelta) {
83+
int minrowd = std::max(-maxdistance, -start.row());
84+
int maxrowd = std::min(maxdistance, maze.rows - start.row() - 1);
85+
const Cell &startcell = maze.at(start);
86+
for (int rowdelta = minrowd; rowdelta <= maxrowd; ++rowdelta) {
87+
int mincold = std::max( -maxdistance + abs(rowdelta), -start.col());
88+
int maxcold = std::min( maxdistance - abs(rowdelta), maze.cols - start.col() - 1);
89+
for (int coldelta = mincold; coldelta <= maxcold; ++coldelta) {
8290
Point delta = {rowdelta, coldelta};
83-
Point end = start + delta;
84-
if (!maze.contains(end))
85-
continue;
86-
const Cell &startcell = maze.at(start);
87-
const Cell &endcell = maze.at(end);
88-
if (!endcell.wall() && endcell.cost > startcell.cost + delta.mag() &&
89-
endcell.cost - startcell.cost - delta.mag() >= threshold)
91+
if (maze.at(start + delta).cost - startcell.cost - delta.mag() >= threshold)
9092
total++;
9193
}
9294
}
9395
}
9496
os << "\n" << total;
9597
}
9698

97-
aoc::Case P1{"part1", [](auto &is, auto &os) { solve(is, os, 2, 100); }};
98-
aoc::Case P2{"part2", [](auto &is, auto &os) { solve(is, os, 20, 100); }};
99-
aoc::Case EG{"eg", [](auto &is, auto &os) { solve(is, os, 20, 50); }};
99+
aoc::Case P1{"part1", [](auto &is, auto &os) { solve<2,100>(is, os); }};
100+
aoc::Case P2{"part2", [](auto &is, auto &os) { solve<20,100>(is, os); }};
100101
}

0 commit comments

Comments
 (0)