Skip to content

Commit ab084a7

Browse files
authored
feat: day07 (#10)
1 parent ae5fb53 commit ab084a7

File tree

16 files changed

+1616
-33
lines changed

16 files changed

+1616
-33
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ members = [
77
"crates/day04",
88
"crates/day05",
99
"crates/day06",
10+
"crates/day07",
1011
"crates/helpers",
1112
]
1213

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ Ideally, the solution does not use external crates/dependencies.
1616
| 3 |||||||
1717
| 4 |||||||
1818
| 5 |||||||
19-
| 6 |||||||
19+
| 6 |||||||
20+
| 7 |||||||

c/day06.c

Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
#include <stdbool.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
6+
#define OBJECT '#'
7+
#define MAX_GRID_SIZE 1000
8+
#define MAX_SET_SIZE 10000
9+
10+
typedef enum { UP, DOWN, LEFT, RIGHT } Direction;
11+
12+
typedef struct {
13+
size_t x;
14+
size_t y;
15+
} Position;
16+
17+
typedef struct {
18+
Position pos1;
19+
Position pos2;
20+
} PositionPair;
21+
22+
typedef struct {
23+
Position pos_init;
24+
char grid[MAX_GRID_SIZE][MAX_GRID_SIZE];
25+
size_t rows;
26+
size_t cols;
27+
} Lab;
28+
29+
typedef struct {
30+
bool is_out;
31+
bool has_pos;
32+
bool has_block;
33+
Position pos;
34+
Position block;
35+
} MoveResult;
36+
37+
typedef struct {
38+
Position positions[MAX_SET_SIZE];
39+
size_t size;
40+
} PositionSet;
41+
42+
typedef struct {
43+
PositionPair pairs[MAX_SET_SIZE];
44+
size_t size;
45+
} PositionPairSet;
46+
47+
void init_position_set(PositionSet *set) { set->size = 0; }
48+
49+
void init_position_pair_set(PositionPairSet *set) { set->size = 0; }
50+
51+
bool position_in_set(PositionSet *set, Position pos) {
52+
for (size_t i = 0; i < set->size; i++) {
53+
if (set->positions[i].x == pos.x && set->positions[i].y == pos.y) {
54+
return true;
55+
}
56+
}
57+
return false;
58+
}
59+
60+
bool position_pair_in_set(PositionPairSet *set, PositionPair pair) {
61+
for (size_t i = 0; i < set->size; i++) {
62+
if (set->pairs[i].pos1.x == pair.pos1.x &&
63+
set->pairs[i].pos1.y == pair.pos1.y &&
64+
set->pairs[i].pos2.x == pair.pos2.x &&
65+
set->pairs[i].pos2.y == pair.pos2.y) {
66+
return true;
67+
}
68+
}
69+
return false;
70+
}
71+
72+
void add_position_to_set(PositionSet *set, Position pos) {
73+
if (!position_in_set(set, pos)) {
74+
set->positions[set->size++] = pos;
75+
}
76+
}
77+
78+
void add_position_pair_to_set(PositionPairSet *set, PositionPair pair) {
79+
if (!position_pair_in_set(set, pair)) {
80+
set->pairs[set->size++] = pair;
81+
}
82+
}
83+
84+
Direction change_direction(Direction direction) {
85+
switch (direction) {
86+
case UP:
87+
return RIGHT;
88+
case RIGHT:
89+
return DOWN;
90+
case DOWN:
91+
return LEFT;
92+
case LEFT:
93+
return UP;
94+
default:
95+
return UP;
96+
}
97+
}
98+
99+
MoveResult change_position(Lab *lab, Direction direction, Position position) {
100+
MoveResult result = {false, false, false, {0, 0}, {0, 0}};
101+
102+
switch (direction) {
103+
case UP:
104+
if (position.y == 0) {
105+
result.is_out = true;
106+
return result;
107+
}
108+
if (lab->grid[position.y - 1][position.x] != OBJECT) {
109+
result.has_pos = true;
110+
result.pos = (Position){position.x, position.y - 1};
111+
} else {
112+
result.has_block = true;
113+
result.block = (Position){position.x, position.y - 1};
114+
}
115+
break;
116+
117+
case LEFT:
118+
if (position.x == 0) {
119+
result.is_out = true;
120+
return result;
121+
}
122+
if (lab->grid[position.y][position.x - 1] != OBJECT) {
123+
result.has_pos = true;
124+
result.pos = (Position){position.x - 1, position.y};
125+
} else {
126+
result.has_block = true;
127+
result.block = (Position){position.x - 1, position.y};
128+
}
129+
break;
130+
131+
case DOWN:
132+
if (position.y + 1 >= lab->rows) {
133+
result.is_out = true;
134+
return result;
135+
}
136+
if (lab->grid[position.y + 1][position.x] != OBJECT) {
137+
result.has_pos = true;
138+
result.pos = (Position){position.x, position.y + 1};
139+
} else {
140+
result.has_block = true;
141+
result.block = (Position){position.x, position.y + 1};
142+
}
143+
break;
144+
145+
case RIGHT:
146+
if (position.x + 1 >= lab->cols) {
147+
result.is_out = true;
148+
return result;
149+
}
150+
if (lab->grid[position.y][position.x + 1] != OBJECT) {
151+
result.has_pos = true;
152+
result.pos = (Position){position.x + 1, position.y};
153+
} else {
154+
result.has_block = true;
155+
result.block = (Position){position.x + 1, position.y};
156+
}
157+
break;
158+
}
159+
return result;
160+
}
161+
162+
Lab *parse_file(const char *filename) {
163+
FILE *file = fopen(filename, "r");
164+
if (!file) {
165+
perror("Failed to open file");
166+
exit(EXIT_FAILURE);
167+
}
168+
169+
Lab *lab = malloc(sizeof(Lab));
170+
char line[MAX_GRID_SIZE];
171+
size_t row = 0;
172+
size_t col_max = 0;
173+
174+
while (fgets(line, sizeof(line), file)) {
175+
size_t len = strlen(line);
176+
if (len > 0 && line[len - 1] == '\n')
177+
line[len--] = '\0';
178+
179+
if (len > col_max)
180+
col_max = len;
181+
182+
for (size_t i = 0; i < len; i++) {
183+
if (line[i] == '^') {
184+
lab->pos_init = (Position){i, row};
185+
lab->grid[row][i] = '.';
186+
} else {
187+
lab->grid[row][i] = line[i];
188+
}
189+
}
190+
row++;
191+
}
192+
193+
lab->rows = row;
194+
lab->cols = col_max;
195+
fclose(file);
196+
return lab;
197+
}
198+
199+
size_t find_path(Lab *lab) {
200+
Direction direction = UP;
201+
Position current_position = lab->pos_init;
202+
PositionSet explored;
203+
init_position_set(&explored);
204+
add_position_to_set(&explored, current_position);
205+
206+
if (current_position.y == 0 ||
207+
(current_position.y > 0 &&
208+
lab->grid[current_position.y][current_position.x] == OBJECT)) {
209+
direction = change_direction(direction);
210+
}
211+
212+
bool second_try = false;
213+
214+
while (true) {
215+
MoveResult result = change_position(lab, direction, current_position);
216+
if (result.is_out)
217+
break;
218+
219+
if (result.has_pos) {
220+
current_position = result.pos;
221+
add_position_to_set(&explored, current_position);
222+
second_try = false;
223+
} else {
224+
direction = change_direction(direction);
225+
if (second_try)
226+
break;
227+
second_try = true;
228+
}
229+
}
230+
231+
return explored.size;
232+
}
233+
234+
size_t find_if_stuck(Lab *lab) {
235+
char original_grid[MAX_GRID_SIZE][MAX_GRID_SIZE];
236+
memcpy(original_grid, lab->grid, sizeof(original_grid));
237+
size_t count = 0;
238+
239+
for (size_t row = 0; row < lab->rows; row++) {
240+
for (size_t col = 0; col < lab->cols; col++) {
241+
if (OBJECT != lab->grid[row][col]) {
242+
lab->grid[row][col] = OBJECT;
243+
Direction direction = UP;
244+
Position current_position = lab->pos_init;
245+
PositionPairSet detect_loop;
246+
init_position_pair_set(&detect_loop);
247+
248+
if (current_position.y == 0 ||
249+
(current_position.y > 0 &&
250+
lab->grid[current_position.y][current_position.x] == OBJECT)) {
251+
direction = change_direction(direction);
252+
}
253+
254+
bool second_try = false;
255+
256+
while (true) {
257+
MoveResult result = change_position(lab, direction, current_position);
258+
if (result.is_out)
259+
break;
260+
261+
if (result.has_pos) {
262+
current_position = result.pos;
263+
second_try = false;
264+
} else if (result.has_block) {
265+
PositionPair blocking = {current_position, result.block};
266+
267+
if (position_pair_in_set(&detect_loop, blocking)) {
268+
count++;
269+
break;
270+
}
271+
direction = change_direction(direction);
272+
add_position_pair_to_set(&detect_loop, blocking);
273+
second_try = true;
274+
}
275+
}
276+
277+
lab->grid[row][col] = original_grid[row][col];
278+
}
279+
}
280+
}
281+
282+
return count;
283+
}
284+
285+
int main() {
286+
Lab *lab = parse_file("crates/day06/input.txt");
287+
288+
// --- Part One ---
289+
printf("Part One solution: %zu\n", find_path(lab));
290+
// --- Part Two ---
291+
printf("Part Two solution: %zu\n", find_if_stuck(lab));
292+
293+
free(lab);
294+
return 0;
295+
}

cpp/day06.cc

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ class Lab {
7272
grid[row][col] = OBJECT;
7373
Direction direction = Direction::Up;
7474
auto current_position = pos_init;
75-
set<tuple<pair<size_t, size_t>, pair<size_t, size_t>, string>>
76-
detect_loop;
75+
set<tuple<pair<size_t, size_t>, pair<size_t, size_t>>> detect_loop;
7776

7877
if (pos_init.second == 0 ||
7978
(pos_init.second > 0 &&
@@ -95,14 +94,12 @@ class Lab {
9594
second_try = false;
9695
}
9796
} else if (block.has_value()) {
98-
string str_direction = to_string(static_cast<int>(direction));
99-
auto blocking =
100-
make_tuple(current_position, block.value(), str_direction);
101-
direction = changeDirection(direction);
97+
auto blocking = make_tuple(current_position, block.value());
10298
if (detect_loop.count(blocking)) {
10399
count += 1;
104100
break;
105101
}
102+
direction = changeDirection(direction);
106103
detect_loop.insert(blocking);
107104
second_try = true;
108105
}
@@ -202,6 +199,8 @@ class Lab {
202199
return Direction::Down;
203200
case Direction::Down:
204201
return Direction::Left;
202+
case Direction::Left:
203+
return Direction::Up;
205204
}
206205
return Direction::Up;
207206
}

0 commit comments

Comments
 (0)