-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
131 lines (106 loc) · 3.61 KB
/
main.cpp
File metadata and controls
131 lines (106 loc) · 3.61 KB
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
127
128
129
130
131
#include <iostream>
#include <chrono>
#include <fstream>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include "../Utils/utils.h"
#include "../Utils/Vector.h"
using aoc_utils::Vector;
typedef std::vector<std::string> puzzle_t;
struct Position{
Vector pos_;
int dangerLevel_;
Position(int y, int x, int dangerLevel) : pos_(x, y), dangerLevel_(dangerLevel) { }
bool operator==(const Position& other) const {
return pos_ == other.pos_ && dangerLevel_ == other.dangerLevel_;
}
};
struct ComparePosition {
bool operator()(const Position& a, const Position& b) {
if(a.dangerLevel_ != b.dangerLevel_){
return a.dangerLevel_ > b.dangerLevel_;
}
if(a.pos_.y != b.pos_.y){
return a.pos_.y < b.pos_.y;
}
return a.pos_.x < b.pos_.x;
}
};
int convertDangerLevel(const puzzle_t& puzzle, const Vector& pos, int stage){
if(stage == 1){
return (puzzle.at(pos.y).at(pos.x) - '0');
}
int x = pos.x % static_cast<int>(puzzle.at(0).length());
int y = pos.y % static_cast<int>(puzzle.size());
int tileX = pos.x / static_cast<int>(puzzle.at(0).length());
int tileY = pos.y / static_cast<int>(puzzle.size());
int increase = tileX+tileY;
int lvl = puzzle.at(y).at(x) - '0';
lvl += increase;
lvl %= 9;
// mod 9, but
if(lvl == 0){
return 9;
}
return lvl;
}
void solvePuzzle(const puzzle_t& puzzle, int stage){
size_t maxY = puzzle.size() * (stage == 1 ? 1 : 5);
size_t maxX = puzzle.at(0).length() * (stage == 1 ? 1 : 5);
std::priority_queue<std::tuple<int, int, int>, std::vector<std::tuple<int, int, int>>, std::greater<> > queue;
std::unordered_set<std::string> visited;
// never entered
queue.emplace(0, 0, 0); // start at (0, 0) with dangerLevel 0
std::array<Vector, 4> directions = {
Vector(0, 1),
Vector(0, -1),
Vector(1, 0),
Vector(-1, 0)
};
while(!queue.empty()){
auto [dangerLevel, x, y] = queue.top();
queue.pop();
Vector pos(x, y);
if(visited.contains(pos.id())){
continue;
}
if(pos.y == maxY-1 && pos.x == maxX - 1){
std::cout << dangerLevel << "\n";
return;
}
visited.insert(pos.id());
for(auto& dir : directions){
Vector newPos = pos + dir;
if(newPos.x < 0 || newPos.x >= maxX || newPos.y < 0 || newPos.y >= maxX){
continue;
}
int newDangerLvl = dangerLevel + convertDangerLevel(puzzle, newPos, stage);
if(!visited.contains(newPos.id())){
queue.emplace(newDangerLvl, newPos.x, newPos.y);
}
}
}
}
void stage1(const puzzle_t& puzzle) {
solvePuzzle(puzzle, 1);
}
void stage2(const puzzle_t& puzzle){
solvePuzzle(puzzle, 2);
}
int main(){
puzzle_t puzzle;
std::string input = "example";
input = "input";
aoc_utils::load_puzzle(input, puzzle);
auto start = std::chrono::high_resolution_clock::now();
stage1(puzzle);
auto end = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> elapsed = end - start;
std::cout << "Stage 1 took " << elapsed.count() << " seconds\n";
start = std::chrono::high_resolution_clock::now();
stage2(puzzle);
end = std::chrono::high_resolution_clock::now();
elapsed = end - start;
std::cout << "Stage 2 took " << elapsed.count() << " seconds\n";
}