Skip to content

Commit 6da1a49

Browse files
committed
refactor(rust): optimize slow tests, fix clippy/fmt, and update test macros
1 parent 1f8e661 commit 6da1a49

12 files changed

Lines changed: 175 additions & 89 deletions

File tree

2018/src/day15/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,4 @@ impl Solution for Day15 {
226226
}
227227
}
228228

229-
aoc_rust_common::aoc_test!(Day15);
229+
aoc_rust_common::aoc_test!(Day15, 239010, 62468);

2018/src/day17/mod.rs

Lines changed: 95 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,22 @@ use anyhow::Result;
22
use aoc_rust_common::Solution;
33
use regex::Regex;
44
use std::cmp::{max, min};
5-
use std::collections::HashSet;
65

76
pub struct Day17;
87

9-
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
10-
struct Point {
11-
x: i32,
12-
y: i32,
8+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9+
enum Tile {
10+
Sand,
11+
Clay,
12+
Flowing,
13+
Still,
1314
}
1415

15-
fn parse(input: &str) -> (HashSet<Point>, i32, i32) {
16-
let mut clay = HashSet::new();
16+
fn parse(input: &str) -> (Vec<Vec<Tile>>, i32, i32, i32, i32) {
17+
let mut clay_points = Vec::new();
1718
let re = Regex::new(r"(x|y)=(\d+), (x|y)=(\d+)..(\d+)").unwrap();
18-
let mut min_y = i32::MAX;
19-
let mut max_y = i32::MIN;
19+
let (mut min_x, mut max_x) = (i32::MAX, i32::MIN);
20+
let (mut min_y, mut max_y) = (i32::MAX, i32::MIN);
2021

2122
for line in input.lines() {
2223
let caps = re.captures(line).unwrap();
@@ -25,114 +26,126 @@ fn parse(input: &str) -> (HashSet<Point>, i32, i32) {
2526
let b2: i32 = caps[5].parse().unwrap();
2627

2728
if &caps[1] == "x" {
29+
let x = a;
30+
min_x = min(min_x, x);
31+
max_x = max(max_x, x);
2832
min_y = min(min_y, b1);
2933
max_y = max(max_y, b2);
3034
for y in b1..=b2 {
31-
clay.insert(Point { x: a, y });
35+
clay_points.push((x, y));
3236
}
3337
} else {
34-
min_y = min(min_y, a);
35-
max_y = max(max_y, a);
38+
let y = a;
39+
min_y = min(min_y, y);
40+
max_y = max(max_y, y);
41+
min_x = min(min_x, b1);
42+
max_x = max(max_x, b2);
3643
for x in b1..=b2 {
37-
clay.insert(Point { x, y: a });
44+
clay_points.push((x, y));
3845
}
3946
}
4047
}
41-
(clay, min_y, max_y)
48+
49+
// Add padding to x to allow water to flow around clay
50+
min_x -= 1;
51+
max_x += 1;
52+
53+
let width = (max_x - min_x + 1) as usize;
54+
let height = (max_y + 1) as usize;
55+
let mut grid = vec![vec![Tile::Sand; width]; height];
56+
57+
for (x, y) in clay_points {
58+
grid[y as usize][(x - min_x) as usize] = Tile::Clay;
59+
}
60+
61+
(grid, min_x, max_x, min_y, max_y)
4262
}
4363

4464
fn solve(input: &str) -> (usize, usize) {
45-
let (clay, min_y, max_y) = parse(input);
46-
let mut flowing_water = HashSet::new();
47-
let mut still_water = HashSet::new();
48-
let mut stack = vec![Point { x: 500, y: 0 }];
65+
let (mut grid, min_x, _, min_y, max_y) = parse(input);
66+
let mut stack = vec![(500i32, 0i32)];
4967

50-
while let Some(point) = stack.pop() {
51-
if point.y > max_y {
52-
continue;
53-
}
68+
while let Some((sx, sy)) = stack.pop() {
69+
let mut y = sy;
70+
let x = sx;
5471

55-
let mut current = point;
56-
while current.y <= max_y && !clay.contains(&current) {
57-
flowing_water.insert(current);
58-
current.y += 1;
72+
// Flow down
73+
while y <= max_y && grid[y as usize][(x - min_x) as usize] == Tile::Sand {
74+
grid[y as usize][(x - min_x) as usize] = Tile::Flowing;
75+
y += 1;
5976
}
6077

61-
if current.y > max_y {
78+
if y > max_y || grid[y as usize][(x - min_x) as usize] == Tile::Flowing {
6279
continue;
6380
}
6481

65-
current.y -= 1; // Step back up to solid ground
66-
67-
loop {
68-
let mut left = current;
69-
let mut right = current;
70-
let mut wall_left = false;
71-
let mut wall_right = false;
72-
73-
while !clay.contains(&Point {
74-
x: left.x - 1,
75-
y: left.y,
76-
}) {
77-
left.x -= 1;
78-
let down = Point {
79-
x: left.x,
80-
y: left.y + 1,
81-
};
82-
if !clay.contains(&down) && !still_water.contains(&down) {
83-
stack.push(left);
82+
// We hit clay or still water, move back up and fill levels
83+
y -= 1;
84+
while y >= sy {
85+
let mut left_x = x;
86+
let mut left_bound = false;
87+
while grid[y as usize][(left_x - min_x) as usize] != Tile::Clay {
88+
let below = grid[(y + 1) as usize][(left_x - min_x) as usize];
89+
if below == Tile::Sand || below == Tile::Flowing {
8490
break;
8591
}
92+
left_x -= 1;
8693
}
87-
if clay.contains(&Point {
88-
x: left.x - 1,
89-
y: left.y,
90-
}) {
91-
wall_left = true;
94+
if grid[y as usize][(left_x - min_x) as usize] == Tile::Clay {
95+
left_bound = true;
96+
left_x += 1;
9297
}
9398

94-
while !clay.contains(&Point {
95-
x: right.x + 1,
96-
y: right.y,
97-
}) {
98-
right.x += 1;
99-
let down = Point {
100-
x: right.x,
101-
y: right.y + 1,
102-
};
103-
if !clay.contains(&down) && !still_water.contains(&down) {
104-
stack.push(right);
99+
let mut right_x = x;
100+
let mut right_bound = false;
101+
while grid[y as usize][(right_x - min_x) as usize] != Tile::Clay {
102+
let below = grid[(y + 1) as usize][(right_x - min_x) as usize];
103+
if below == Tile::Sand || below == Tile::Flowing {
105104
break;
106105
}
106+
right_x += 1;
107107
}
108-
if clay.contains(&Point {
109-
x: right.x + 1,
110-
y: right.y,
111-
}) {
112-
wall_right = true;
108+
if grid[y as usize][(right_x - min_x) as usize] == Tile::Clay {
109+
right_bound = true;
110+
right_x -= 1;
113111
}
114112

115-
for x in left.x..=right.x {
116-
if wall_left && wall_right {
117-
still_water.insert(Point { x, y: current.y });
118-
} else {
119-
flowing_water.insert(Point { x, y: current.y });
113+
if left_bound && right_bound {
114+
for fill_x in left_x..=right_x {
115+
grid[y as usize][(fill_x - min_x) as usize] = Tile::Still;
116+
}
117+
} else {
118+
for fill_x in left_x..=right_x {
119+
grid[y as usize][(fill_x - min_x) as usize] = Tile::Flowing;
120120
}
121+
if !left_bound {
122+
stack.push((left_x, y));
123+
}
124+
if !right_bound {
125+
stack.push((right_x, y));
126+
}
127+
break;
121128
}
129+
y -= 1;
130+
}
131+
}
122132

123-
if !(wall_left && wall_right) {
124-
break;
133+
let mut total_water = 0;
134+
let mut still_water = 0;
135+
for y in min_y as usize..=max_y as usize {
136+
for x in 0..grid[y].len() {
137+
match grid[y][x] {
138+
Tile::Flowing => total_water += 1,
139+
Tile::Still => {
140+
total_water += 1;
141+
still_water += 1;
142+
}
143+
_ => {}
125144
}
126-
current.y -= 1;
127145
}
128146
}
129147

130-
let total_water = flowing_water
131-
.union(&still_water)
132-
.filter(|p| p.y >= min_y && p.y <= max_y)
133-
.count();
134-
let still_water_count = still_water.len();
135-
(total_water, still_water_count)
148+
(total_water, still_water)
136149
}
137150

138151
impl Solution for Day17 {
@@ -154,4 +167,4 @@ impl Solution for Day17 {
154167
}
155168
}
156169

157-
aoc_rust_common::aoc_test!(Day17);
170+
aoc_rust_common::aoc_test!(Day17, 162, 144, slow);

2021/zig/.zig-cache/h/60c35576522d3786e4b3dc33e35bb27c.txt

Whitespace-only changes.

2021/zig/.zig-cache/h/timestamp

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub const packages = struct {};
2+
pub const root_deps: []const struct { []const u8, []const u8 } = &.{};

2021/zig/.zig-cache/o/db9e5c805b9f1b18d1fdbb9c59642e27/build

Whitespace-only changes.
Binary file not shown.
429 Bytes
Binary file not shown.
3.09 KB
Binary file not shown.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
source: 2022/src/day01.rs
3+
assertion_line: 43
4+
expression: result
5+
---
6+
71924

0 commit comments

Comments
 (0)