Skip to content

Commit 6af6268

Browse files
committed
day 18 part 1
1 parent f20c568 commit 6af6268

File tree

3 files changed

+201
-2
lines changed

3 files changed

+201
-2
lines changed

2024/src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ create_standard_test(NAME 2024_day14 SOURCES day14.cpp LIBRARIES aoc2024)
2828
create_standard_test(NAME 2024_day15 SOURCES day15.cpp LIBRARIES aoc2024)
2929
create_standard_test(NAME 2024_day16 SOURCES day16.cpp LIBRARIES aoc2024)
3030
create_standard_test(NAME 2024_day17 SOURCES day17.cpp LIBRARIES aoc2024)
31+
create_standard_test(NAME 2024_day18 SOURCES day18.cpp LIBRARIES aoc2024)
3132

3233
################################################################################
3334
# Copy input data

2024/src/day16.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ struct State {
2929
}
3030
};
3131

32-
// int64_t count(std::map<State, std:)
33-
3432
std::pair<int64_t, int64_t> djikstra(const Data &data)
3533
{
3634
int64_t width = data.grid[0].size();

2024/src/day18.cpp

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
#include <iostream>
2+
#include <filesystem>
3+
#include <fstream>
4+
#include <string>
5+
#include <vector>
6+
#include <benchmark/benchmark.h>
7+
#include <format>
8+
#include <aoc/2024/pos.h>
9+
#include <aoc/2024/split.h>
10+
#include <map>
11+
#include <set>
12+
13+
struct Data {
14+
std::vector<Pos> positions;
15+
Pos start;
16+
Pos end;
17+
};
18+
19+
bool in_bounds(const Pos &pos, int width, int height)
20+
{
21+
return pos.x >= 0 && pos.x < width && pos.y >= 0 && pos.y < height;
22+
}
23+
24+
struct State {
25+
Pos pos;
26+
Pos dir;
27+
bool operator<(const State& other) const {
28+
return std::tie(pos.x, pos.y, dir.x, dir.y) < std::tie(other.pos.x, other.pos.y, other.dir.x, other.dir.y);
29+
}
30+
};
31+
32+
std::pair<int64_t, int64_t> djikstra(const Data& data, int64_t width, int64_t height, int64_t limit)
33+
{
34+
std::set<Pos> occupied;
35+
for(size_t i = 0; i < limit; ++i) {
36+
occupied.insert(data.positions[i]);
37+
}
38+
std::priority_queue<std::pair<int64_t, State>, std::vector<std::pair<int64_t, State>>, std::greater<>> pq;
39+
std::map<State, int64_t> dist;
40+
std::map<State, std::vector<State>> prev;
41+
std::set<State> visited;
42+
43+
State start = State{.pos = data.start, .dir = E};
44+
pq.emplace(0, start);
45+
dist[start] = 0;
46+
State end_state;
47+
48+
int64_t distance = 0;
49+
while (!pq.empty()) {
50+
auto elem = pq.top();
51+
pq.pop();
52+
int64_t cur_dist = elem.first;
53+
State u = elem.second;
54+
visited.insert(u);
55+
56+
if (u.pos == data.end) {
57+
end_state = u;
58+
distance = cur_dist;
59+
break;
60+
}
61+
62+
for(auto& new_dir : directions) {
63+
State v = {.pos = u.pos + new_dir, .dir = new_dir};
64+
65+
if (!in_bounds(v.pos, width, height) || visited.contains(v) || occupied.contains(v.pos)) {
66+
continue;
67+
}
68+
69+
int64_t new_dist = cur_dist + 1;
70+
if (!dist.contains(v) || new_dist < dist[v]) {
71+
dist[v] = new_dist;
72+
prev[v] = {u};
73+
pq.emplace(new_dist, v);
74+
}
75+
else if (new_dist == dist[v]) {
76+
prev[v].push_back(u);
77+
}
78+
}
79+
}
80+
81+
82+
std::vector<std::string> grid(height, std::string(width, '.'));
83+
84+
std::vector<State> stack;
85+
stack.push_back(end_state);
86+
std::set<Pos> visited_pos;
87+
while (stack.size() != 0 && stack[0].pos != data.start) {
88+
visited_pos.insert(stack.back().pos);
89+
auto cur = stack.back();
90+
grid[cur.pos.y][cur.pos.x] = 'O';
91+
stack.pop_back();
92+
stack.push_back(prev[cur][0]);
93+
// for(auto& prev_state : prev[cur]) {
94+
// stack.push_back(prev_state);
95+
// }
96+
}
97+
grid[data.start.y][data.start.x] = 'O';
98+
99+
for(size_t i = 0; i < limit; ++i) {
100+
grid[data.positions[i].y][data.positions[i].x] = '#';
101+
}
102+
103+
for(auto& row : grid) {
104+
std::cout << row << std::endl;
105+
}
106+
std::cout << std::endl;
107+
108+
return {distance, visited_pos.size()};
109+
}
110+
111+
int part1(const Data &data)
112+
{
113+
auto copy = data;
114+
int64_t width = 71;
115+
int64_t height = 71;
116+
copy.start = Pos{.x = 0, .y = 0};
117+
copy.end = Pos{.x = width - 1, .y = height - 1};
118+
auto [distance, visited] = djikstra(copy, width, height, 1024);
119+
return distance;
120+
}
121+
122+
int part2(const Data &data)
123+
{
124+
return 0;
125+
}
126+
127+
Data parse()
128+
{
129+
std::ifstream file(std::filesystem::path("inputs/day18.txt"));
130+
if (!file.is_open())
131+
{
132+
throw std::runtime_error("file not found");
133+
}
134+
std::string line;
135+
Data data;
136+
137+
while (std::getline(file, line))
138+
{
139+
auto location = split_to_int(line, ",");
140+
data.positions.push_back(Pos{.x = location[0], .y = location[1]});
141+
}
142+
143+
return data;
144+
}
145+
146+
class BenchmarkFixture : public benchmark::Fixture
147+
{
148+
public:
149+
static Data data;
150+
};
151+
152+
Data BenchmarkFixture::data = parse();
153+
154+
BENCHMARK_DEFINE_F(BenchmarkFixture, Part1Benchmark)
155+
(benchmark::State &state)
156+
{
157+
for (auto _ : state)
158+
{
159+
auto s = part1(data);
160+
benchmark::DoNotOptimize(s);
161+
}
162+
}
163+
164+
BENCHMARK_DEFINE_F(BenchmarkFixture, Part2Benchmark)
165+
(benchmark::State &state)
166+
{
167+
for (auto _ : state)
168+
{
169+
auto s = part2(data);
170+
benchmark::DoNotOptimize(s);
171+
}
172+
}
173+
174+
BENCHMARK_REGISTER_F(BenchmarkFixture, Part1Benchmark)->Unit(benchmark::kMillisecond);
175+
BENCHMARK_REGISTER_F(BenchmarkFixture, Part2Benchmark)->Unit(benchmark::kMillisecond);
176+
177+
int main(int argc, char **argv)
178+
{
179+
Data data = parse();
180+
181+
int answer1 = 0;
182+
int answer2 = 0;
183+
184+
auto first = part1(data);
185+
std::cout << "Part 1: " << first << std::endl;
186+
187+
auto second = part2(data);
188+
std::cout << "Part 2: " << second << std::endl;
189+
190+
first != answer1 ? throw std::runtime_error("Part 1 incorrect") : nullptr;
191+
second != answer2 ? throw std::runtime_error("Part 2 incorrect") : nullptr;
192+
193+
for (int i = 1; i < argc; ++i) {
194+
if (std::string(argv[i]) == "--benchmark") {
195+
benchmark::Initialize(&argc, argv);
196+
benchmark::RunSpecifiedBenchmarks();
197+
return 0;
198+
}
199+
}
200+
}

0 commit comments

Comments
 (0)