Skip to content

Commit a5143fe

Browse files
committed
Faster approach using reverse linked list of dominator nodes
1 parent 77a2202 commit a5143fe

File tree

2 files changed

+58
-71
lines changed

2 files changed

+58
-71
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ pie
120120
| 19 | [Aplenty](https://adventofcode.com/2023/day/19) | [Source](src/year2023/day19.rs) | 100 |
121121
| 20 | [Pulse Propagation](https://adventofcode.com/2023/day/20) | [Source](src/year2023/day20.rs) | 6 |
122122
| 21 | [Step Counter](https://adventofcode.com/2023/day/21) | [Source](src/year2023/day21.rs) | 180 |
123-
| 22 | [Sand Slabs](https://adventofcode.com/2023/day/22) | [Source](src/year2023/day22.rs) | 486 |
123+
| 22 | [Sand Slabs](https://adventofcode.com/2023/day/22) | [Source](src/year2023/day22.rs) | 41 |
124124
| 23 | [A Long Walk](https://adventofcode.com/2023/day/23) | [Source](src/year2023/day23.rs) | 3181 |
125125
| 24 | [Never Tell Me The Odds](https://adventofcode.com/2023/day/24) | [Source](src/year2023/day24.rs) | 96 |
126126
| 25 | [Snowverload](https://adventofcode.com/2023/day/25) | [Source](src/year2023/day25.rs) | 157 |

src/year2023/day22.rs

Lines changed: 57 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,87 @@
1-
#![allow(clippy::needless_range_loop)]
2-
31
use crate::util::iter::*;
42
use crate::util::parse::*;
5-
use std::collections::VecDeque;
63

7-
pub struct Input {
8-
up: Vec<Vec<usize>>,
9-
down: Vec<Vec<usize>>,
10-
}
4+
type Input = (usize, usize);
115

126
pub fn parse(input: &str) -> Input {
137
let mut bricks: Vec<_> = input.iter_unsigned::<usize>().chunk::<6>().collect();
14-
let mut heights = [[0; 10]; 10];
15-
let mut indices = [[usize::MAX; 10]; 10];
16-
let mut up = vec![Vec::new(); bricks.len()];
17-
let mut down = vec![Vec::new(); bricks.len()];
8+
let mut heights = [0; 100];
9+
let mut indices = [usize::MAX; 100];
10+
11+
let mut safe = vec![true; bricks.len()];
12+
let mut dominator: Vec<(usize, usize)> = Vec::with_capacity(bricks.len());
1813

1914
// Sort ascending by lowest z coordinate.
2015
bricks.sort_unstable_by_key(|b| b[2]);
2116

2217
for (i, &[x1, y1, z1, x2, y2, z2]) in bricks.iter().enumerate() {
18+
let start = 10 * y1 + x1;
19+
let end = 10 * y2 + x2;
20+
let step = if y2 > y1 { 10 } else { 1 };
2321
let height = z2 - z1 + 1;
22+
2423
let mut top = 0;
2524
let mut previous = usize::MAX;
25+
let mut underneath = 0;
26+
let mut parent = 0;
27+
let mut depth = 0;
2628

27-
for x in x1..=x2 {
28-
for y in y1..=y2 {
29-
top = top.max(heights[x][y]);
30-
}
29+
for j in (start..=end).step_by(step) {
30+
top = top.max(heights[j]);
3131
}
3232

33-
for x in x1..=x2 {
34-
for y in y1..=y2 {
35-
if heights[x][y] == top {
36-
let index = indices[x][y];
37-
if index != previous {
38-
up[index].push(i);
39-
down[i].push(index);
40-
previous = index;
33+
for j in (start..=end).step_by(step) {
34+
if heights[j] == top {
35+
let index = indices[j];
36+
if index != previous {
37+
previous = index;
38+
underneath += 1;
39+
40+
if underneath == 1 {
41+
(parent, depth) = dominator[previous];
42+
} else {
43+
// Find common ancestor
44+
let (mut a, mut b) = (parent, depth);
45+
let (mut x, mut y) = dominator[previous];
46+
47+
while b > y {
48+
(a, b) = dominator[a];
49+
}
50+
while y > b {
51+
(x, y) = dominator[x];
52+
}
53+
while a != x {
54+
(a, b) = dominator[a];
55+
(x, _) = dominator[x];
56+
}
57+
58+
(parent, depth) = (a, b);
4159
}
4260
}
43-
44-
heights[x][y] = top + height;
45-
indices[x][y] = i;
4661
}
62+
63+
heights[j] = top + height;
64+
indices[j] = i;
4765
}
66+
67+
if underneath == 1 {
68+
safe[previous] = false;
69+
parent = previous;
70+
depth = dominator[previous].1 + 1;
71+
}
72+
73+
dominator.push((parent, depth));
4874
}
4975

50-
Input { up, down }
76+
let part_one = safe.iter().filter(|&&b| b).count();
77+
let part_two = dominator.iter().map(|(_, d)| d).sum();
78+
(part_one, part_two)
5179
}
5280

5381
pub fn part1(input: &Input) -> usize {
54-
let Input { down, .. } = input;
55-
let mut safe = vec![true; down.len()];
56-
57-
for underneath in down {
58-
if underneath.len() == 1 {
59-
safe[underneath[0]] = false;
60-
}
61-
}
62-
63-
safe.iter().filter(|&&b| b).count()
82+
input.0
6483
}
6584

6685
pub fn part2(input: &Input) -> usize {
67-
let Input { up, down } = input;
68-
let mut safe = vec![true; down.len()];
69-
70-
for underneath in down {
71-
if underneath.len() == 1 {
72-
safe[underneath[0]] = false;
73-
}
74-
}
75-
76-
let mut result = 0;
77-
let mut todo = VecDeque::new();
78-
let mut removed = vec![usize::MAX; down.len()];
79-
80-
for (start, &safe) in safe.iter().enumerate() {
81-
if safe {
82-
continue;
83-
}
84-
85-
todo.push_back(start);
86-
removed[start] = start;
87-
88-
while let Some(current) = todo.pop_front() {
89-
for &next in &up[current] {
90-
if removed[next] != start && down[next].iter().all(|&i| removed[i] == start) {
91-
result += 1;
92-
removed[next] = start;
93-
todo.push_back(next);
94-
}
95-
}
96-
}
97-
}
98-
99-
result
86+
input.1
10087
}

0 commit comments

Comments
 (0)