tangled
alpha
login
or
join now
bwc9876.dev
/
advent
0
fork
atom
Advent of Code solutions
0
fork
atom
overview
issues
pulls
pipelines
Day 12
bwc9876.dev
3 months ago
e953ece2
9ae06fd4
verified
This commit was signed with the committer's
known signature
.
bwc9876.dev
SSH Key Fingerprint:
SHA256:DanMEP/RNlSC7pAVbnXO6wzQV00rqyKj053tz4uH5gQ=
+198
-5
2 changed files
expand all
collapse all
unified
split
years
2025
src
day_12.rs
examples
day_12
1.txt
+166
-5
years/2025/src/day_12.rs
···
1
1
use advent_core::{day_stuff, ex_for_day, Day};
2
2
+
use rayon::iter::{IntoParallelIterator, ParallelIterator};
3
3
+
use utils::{grid::Grid, pos::Position, tiles, upos, yippee};
2
4
3
5
pub struct Day12;
4
6
7
7
+
tiles!(Tile, [
8
8
+
'#' => Filled,
9
9
+
'.' => Empty,
10
10
+
]);
11
11
+
12
12
+
type Present = utils::grid::Grid<Tile>;
13
13
+
type Input = (Vec<[Vec<Position>; 4]>, Vec<((usize, usize), Vec<usize>)>);
14
14
+
15
15
+
pub const KERNS: [Position; 9] = [
16
16
+
Position::new(0, 0),
17
17
+
Position::new(0, -1),
18
18
+
Position::new(0, 1),
19
19
+
Position::new(1, 0),
20
20
+
Position::new(-1, 0),
21
21
+
Position::new(1, 1),
22
22
+
Position::new(1, -1),
23
23
+
Position::new(-1, 1),
24
24
+
Position::new(-1, -1),
25
25
+
];
26
26
+
27
27
+
fn rot_pos(Position { x, y }: Position) -> Position {
28
28
+
let (x, y) = match (x, y) {
29
29
+
(0, 0) => (0, 0),
30
30
+
(1, 0) => (0, -1),
31
31
+
(0, -1) => (-1, 0),
32
32
+
(-1, 0) => (0, 1),
33
33
+
(0, 1) => (1, 0),
34
34
+
(1, 1) => (1, -1),
35
35
+
(1, -1) => (-1, -1),
36
36
+
(-1, -1) => (-1, 1),
37
37
+
(-1, 1) => (1, 1),
38
38
+
_ => unreachable!(),
39
39
+
};
40
40
+
Position::new(x, y)
41
41
+
}
42
42
+
43
43
+
fn try_place_at(pos: Position, shape: &[Position], grid: &mut Present) -> bool {
44
44
+
let empties = grid
45
45
+
.relatives(pos, shape)
46
46
+
.take_while(|(_, _, t)| **t == Tile::Empty)
47
47
+
.map(|(_, p, _)| p)
48
48
+
.collect::<Vec<_>>();
49
49
+
50
50
+
if empties.len() == shape.len() {
51
51
+
for pos in empties {
52
52
+
*(grid.get_mut(pos).unwrap()) = Tile::Filled;
53
53
+
}
54
54
+
true
55
55
+
} else {
56
56
+
false
57
57
+
}
58
58
+
}
59
59
+
60
60
+
fn undo_place(pos: Position, shape: &[Position], grid: &mut Present) {
61
61
+
let positions = grid
62
62
+
.relatives(pos, shape)
63
63
+
.map(|(_, p, _)| p)
64
64
+
.collect::<Vec<_>>();
65
65
+
66
66
+
for pos in positions {
67
67
+
*(grid.get_mut(pos).unwrap()) = Tile::Empty;
68
68
+
}
69
69
+
}
70
70
+
71
71
+
fn solve(shapes: &Vec<[Vec<Position>; 4]>, grid: &mut Present, targets: &mut Vec<usize>) -> bool {
72
72
+
let next_shape = targets
73
73
+
.iter()
74
74
+
.enumerate()
75
75
+
.find(|(_, amnt)| **amnt != 0)
76
76
+
.map(|(f, _)| f);
77
77
+
78
78
+
let (x, y) = grid.size();
79
79
+
80
80
+
if let Some(next_shape) = next_shape {
81
81
+
let shape_all_rots = shapes.get(next_shape).unwrap();
82
82
+
for y in 1..(y - 1) {
83
83
+
for x in 1..(x - 1) {
84
84
+
for shape in shape_all_rots {
85
85
+
if try_place_at(upos!(x, y), shape.as_slice(), grid) {
86
86
+
targets[next_shape] -= 1;
87
87
+
let inner_res = solve(shapes, grid, targets);
88
88
+
if inner_res {
89
89
+
return inner_res;
90
90
+
} else {
91
91
+
targets[next_shape] += 1;
92
92
+
undo_place(upos!(x, y), shape.as_slice(), grid);
93
93
+
}
94
94
+
}
95
95
+
}
96
96
+
}
97
97
+
}
98
98
+
false
99
99
+
} else {
100
100
+
true
101
101
+
}
102
102
+
}
103
103
+
5
104
impl Day for Day12 {
6
6
-
day_stuff!(12, "", "");
105
105
+
day_stuff!(12, "2", "🥳", Input);
106
106
+
107
107
+
fn part_1((shapes, targets): Self::Input) -> Option<String> {
108
108
+
let ans = targets
109
109
+
.into_par_iter()
110
110
+
.filter_map(|((x, y), mut avail)| {
111
111
+
let area_needed = shapes
112
112
+
.iter()
113
113
+
.enumerate()
114
114
+
.map(|(i, s)| s[0].len() * avail[i])
115
115
+
.sum::<usize>();
116
116
+
if area_needed > (x * y) {
117
117
+
return None;
118
118
+
}
119
119
+
let mut grid = Grid::new(vec![vec![Tile::Empty; x]; y]);
120
120
+
let can_fit = solve(&shapes, &mut grid, &mut avail);
121
121
+
if can_fit {
122
122
+
Some(0)
123
123
+
} else {
124
124
+
None
125
125
+
}
126
126
+
})
127
127
+
.count();
7
128
8
8
-
fn part_1(_input: Self::Input) -> Option<String> {
9
9
-
None
129
129
+
Some(ans.to_string())
10
130
}
11
131
12
12
-
fn part_2(_input: Self::Input) -> Option<String> {
13
13
-
None
132
132
+
yippee!();
133
133
+
134
134
+
fn parse_input(input: &str) -> Self::Input {
135
135
+
let sections = input.split("\n\n").collect::<Vec<_>>();
136
136
+
let shapes = sections
137
137
+
.iter()
138
138
+
.take(sections.len() - 1)
139
139
+
.map(|s| {
140
140
+
let (_, grid) = s.split_once('\n').unwrap();
141
141
+
let grid = Present::parse(grid);
142
142
+
let rels = grid
143
143
+
.relatives(Position::new(1, 1), &KERNS)
144
144
+
.filter(|(_, _, t)| **t == Tile::Filled)
145
145
+
.map(|(kern, _, _)| kern)
146
146
+
.collect::<Vec<_>>();
147
147
+
148
148
+
let rels90: Vec<_> = rels.iter().copied().map(rot_pos).collect();
149
149
+
150
150
+
let rels180: Vec<_> = rels90.iter().copied().map(rot_pos).collect();
151
151
+
152
152
+
let rels270: Vec<_> = rels180.iter().copied().map(rot_pos).collect();
153
153
+
154
154
+
[rels, rels90, rels180, rels270]
155
155
+
})
156
156
+
.collect();
157
157
+
158
158
+
let targets = sections
159
159
+
.last()
160
160
+
.unwrap()
161
161
+
.lines()
162
162
+
.map(|l| {
163
163
+
let (size, amnts) = l.split_once(':').unwrap();
164
164
+
let (x, y) = size.split_once('x').unwrap();
165
165
+
let amnts = amnts
166
166
+
.trim()
167
167
+
.split(' ')
168
168
+
.map(|x| x.parse().unwrap())
169
169
+
.collect();
170
170
+
((x.parse().unwrap(), y.parse().unwrap()), amnts)
171
171
+
})
172
172
+
.collect();
173
173
+
174
174
+
(shapes, targets)
14
175
}
15
176
}
+32
years/2025/src/examples/day_12/1.txt
···
1
1
+
0:
2
2
+
###
3
3
+
##.
4
4
+
##.
5
5
+
6
6
+
1:
7
7
+
###
8
8
+
##.
9
9
+
.##
10
10
+
11
11
+
2:
12
12
+
.##
13
13
+
###
14
14
+
##.
15
15
+
16
16
+
3:
17
17
+
##.
18
18
+
###
19
19
+
##.
20
20
+
21
21
+
4:
22
22
+
###
23
23
+
#..
24
24
+
###
25
25
+
26
26
+
5:
27
27
+
###
28
28
+
.#.
29
29
+
###
30
30
+
31
31
+
4x4: 0 0 0 0 2 0
32
32
+
12x5: 1 0 1 0 2 2