-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathday_14b.cpp
146 lines (133 loc) · 3.61 KB
/
day_14b.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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include <fstream>
#include <iostream>
#include <string>
#include <unordered_set>
#include <vector>
struct Point {
Point(const int row, const int col) : row(row), col(col) {}
int row, col;
bool operator == (const Point& p) const {
return p.row == row && p.col == col;
}
bool operator != (const Point& p) const {
return row != p.row || col != p.col;
}
};
struct PointHash {
std::size_t operator() (const Point& p) const {
return p.row * p.col;
}
};
void print_point(const Point& p) {
std::cout << p.row << ' ' << p.col<< '\n';
}
Point get_delta(const Point& previous, const Point& current) {
const auto delta_row = current.row-previous.row;
const auto delta_col = current.col-previous.col;
return Point(
delta_row == 0 ? 0 : delta_row / std::abs(delta_row),
delta_col == 0 ? 0 : delta_col / std::abs(delta_col)
);
}
Point add_points_to_set(
const std::string& line,
std::unordered_set<Point, PointHash>& occupied
) {
Point lowest(0, 0);
size_t start = 0;
size_t end = line.find(" -> ");
auto mid = line.find(',', start);
auto col = std::stoi(line.substr(start, mid));
auto row = std::stoi(line.substr(mid+1, end));
Point previous(row, col);
if (row > lowest.row) lowest.row = row;
occupied.insert(previous);
start = end + 4;
end = line.find(" -> ", start);
while(end != std::string::npos) {
mid = line.find(',', start);
col = std::stoi(line.substr(start, mid-start));
row = std::stoi(line.substr(mid+1, end-mid-1));
if (row > lowest.row) lowest.row = row;
const auto current = Point(row, col);
const auto delta = get_delta(previous, current);
auto transition = current;
while(transition != previous) {
occupied.insert(transition);
transition.row -= delta.row;
transition.col -= delta.col;
}
start = end + 4;
end = line.find(" -> ", start);
previous = current;
}
mid = line.find(',', start);
col = std::stoi(line.substr(start, mid-start));
row = std::stoi(line.substr(mid+1, end-mid-1));
if (row > lowest.row) lowest.row = row;
auto current = Point(row, col);
const auto delta = get_delta(previous, current);
while(current != previous) {
occupied.insert(current);
current.row -= delta.row;
current.col -= delta.col;
}
return lowest;
}
int simulate(
std::unordered_set<Point, PointHash>& occupied,
const Point& floor
) {
const auto moves = std::vector<Point> {
{1,0},
{1,-1},
{1,1}
};
int count = 0;
const Point start (0, 500);
while (true) {
count++;
Point sand = start;
bool moving = true;
while (moving) {
moving = false;
for (const auto& move : moves) {
const auto new_sand = Point(sand.row + move.row, sand.col + move.col);
if (occupied.find(new_sand) == occupied.end()) {
moving = true;
if (new_sand.row == floor.row) {
moving = false;
break;
}
sand = new_sand;
break;
}
}
if (!moving) {
occupied.insert(sand);
if (sand == start) {
return count;
}
}
}
}
return count;
}
int main(int argc, char * argv[]) {
std::string input = "../input/day_14_input";
if (argc > 1) {
input = argv[1];
}
std::string line;
std::fstream file(input);
std::unordered_set<Point, PointHash> occupied;
Point lowest(0,0);
while(std::getline(file, line)) {
const auto new_lowest = add_points_to_set(line, occupied);
if (new_lowest.row > lowest.row) lowest.row = new_lowest.row;
}
lowest.row += 2;
const auto count = simulate(occupied, lowest);
std::cout << count << '\n';
return 0;
}