-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
104 lines (89 loc) · 3.7 KB
/
main.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
#include "file.h"
#include "utilities.h"
#include "direction.h"
#include <iostream>
#ifdef TESTING
#include <gtest/gtest.h>
#endif
namespace aoc2023_day17 {
int solve(std::string_view path, int minDist, int maxDist) {
struct state {
state(int _x, int _y, int _d, int _v) : x(_x), y(_y), direction(_d), value(_v) {}
int x;
int y;
int direction;
int value;
};
std::vector<std::vector<int>> input = file::readFileAsMap(path);
std::vector<state> points;
points.emplace_back(0, 0, -1, 0);
direction::Direction d;
std::vector<std::vector<std::array<bool, 4>>> visited(input.size(), std::vector<std::array<bool, 4>>(input[0].size(), {false, false, false, false}));
std::vector<std::vector<std::array<int, 4>>> costs(input.size(), std::vector<std::array<int, 4>>(input[0].size(), {1000000, 1000000, 1000000, 1000000}));
while (!points.empty()) {
std::pop_heap(points.begin(), points.end(),[](const auto& p1, const auto& p2) {
return p1.value > p2.value;
});
state p = points.back();
points.pop_back();
if (p.direction >= 0 && visited[p.x][p.y][p.direction]) {
continue;
}
if (p.direction >= 0) {
visited[p.x][p.y][p.direction] = true;
}
if (p.x == input.size() - 1 && p.y == input[0].size() - 1) {
return p.value;
}
for (int direction = 0; direction < d.directions.size(); ++direction) {
if (direction == p.direction || (std::abs(d.directions[direction].x) == std::abs(d.directions[p.direction].x) &&
std::abs(d.directions[direction].y) == std::abs(d.directions[p.direction].y))) {
// we are going back
continue;
}
int extra = 0;
for (int j = 0; j < maxDist; ++j) {
int x = p.x + d.directions[direction].x * (j + 1);
int y = p.y + d.directions[direction].y * (j + 1);
if (x >= 0 && x < input.size() && y >= 0 && y < input[0].size()) {
extra += input[x][y];
if ((j >= minDist - 1) && (costs[x][y][direction] == 1000000 || costs[x][y][direction] > p.value + extra)) {
costs[x][y][direction] = p.value + extra;
points.emplace_back(x, y, direction, p.value + extra);
std::push_heap(points.begin(), points.end(),[](const auto& p1, const auto& p2) {
return p1.value > p2.value;
});
}
}
}
}
}
}
unsigned long long part_1(std::string_view path) {
return solve(path, 1, 3);
}
unsigned long long part_2(std::string_view path) {
return solve(path, 4, 10);
}
}
#ifdef TESTING
TEST(Tests2023Day17, part_1_test) {
ASSERT_EQ(aoc2023_day17::part_1("../2023/day17/input_test.in"), 102);
}
TEST(Tests2023Day17, part_1_real_test) {
ASSERT_EQ(aoc2023_day17::part_1("../2023/day17/input.in"), 758);
}
TEST(Tests2023Day17, part_2_test) {
ASSERT_EQ(aoc2023_day17::part_2("../2023/day17/input_test.in"), 94);
}
TEST(Tests2023Day17, part_2_real_test) {
ASSERT_EQ(aoc2023_day17::part_2("../2023/day17/input.in"), 892);
}
#endif
#ifndef TESTING
int main() {
std::cout << "Part 1: " << aoc2023_day17::part_1("../2023/day17/input.in") << std::endl;
std::cout << "Part 2: " << aoc2023_day17::part_2("../2023/day17/input.in") << std::endl;
return 0;
}
#endif