Skip to content

Commit d208d34

Browse files
committed
solve: day14
1 parent 32cd9df commit d208d34

File tree

3 files changed

+124
-1
lines changed

3 files changed

+124
-1
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
resolver = "2"
33
members = [
44
"utils",
5-
"aoc_derive", "day1", "day2", "day3", "day4", "day5", "day6", "day7", "day8", "day9", "day10", "day11", "day12", "day13",
5+
"aoc_derive", "day1", "day2", "day3", "day4", "day5", "day6", "day7", "day8", "day9", "day10", "day11", "day12", "day13", "day14",
66
]
77

88
[workspace.dependencies]

day14/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "day14"
3+
version = "0.1.0"
4+
edition = "2024"
5+
6+
[dependencies]
7+
aoc_derive.path = '../aoc_derive'
8+
utils.path = '../utils'
9+
derive_more.workspace = true
10+
itertools.workspace = true
11+
lazy-regex.workspace = true
12+
parse-display.workspace = true
13+
rayon.workspace = true
14+
regex.workspace = true
15+
num.workspace = true
16+
17+
[dev-dependencies]
18+
pretty_assertions.workspace = true

day14/src/main.rs

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use std::str::FromStr;
2+
3+
use aoc_derive::aoc_main;
4+
use itertools::Itertools;
5+
use lazy_regex::regex_is_match;
6+
use math::Vec2D;
7+
use utils::*;
8+
9+
#[derive(Debug, Clone)]
10+
struct Robot {
11+
pos: Vec2D,
12+
velocity: Vec2D,
13+
}
14+
15+
impl Robot {
16+
fn move_(mut self, width: i64, height: i64) -> Self {
17+
self.pos += self.velocity + (width, height);
18+
19+
self.pos.x %= width;
20+
self.pos.y %= height;
21+
22+
self
23+
}
24+
}
25+
26+
impl FromStr for Robot {
27+
type Err = ();
28+
29+
fn from_str(s: &str) -> Result<Self, Self::Err> {
30+
let (x, y, vx, vy) = extract_numbers::<i64>(s).collect_tuple().unwrap();
31+
Ok(Self { pos: (x, y).into(), velocity: (vx, vy).into() })
32+
}
33+
}
34+
35+
fn count_robots(robots: &[Robot], width: i64, height: i64) -> usize {
36+
robots.iter().filter(|r| r.pos.x < width / 2 && r.pos.y < height / 2).count()
37+
* robots.iter().filter(|r| r.pos.x < width / 2 && r.pos.y > height / 2).count()
38+
* robots.iter().filter(|r| r.pos.x > width / 2 && r.pos.y < height / 2).count()
39+
* robots.iter().filter(|r| r.pos.x > width / 2 && r.pos.y > height / 2).count()
40+
}
41+
42+
fn part1(robots: impl Iterator<Item = Robot>, width: i64, height: i64) -> usize {
43+
let robots = robots
44+
.into_iter()
45+
.map(|robot| (0..100).fold(robot, |robot, _| robot.move_(width, height)))
46+
.collect_vec();
47+
count_robots(&robots, width, height)
48+
}
49+
50+
fn part2(mut robots: Vec<Robot>, width: usize, height: usize) -> usize {
51+
(1..)
52+
.find(|_| {
53+
robots =
54+
robots.clone().into_iter().map(|r| r.move_(width as i64, height as i64)).collect();
55+
56+
let lines = (0..height)
57+
.map(|y| {
58+
(0..width)
59+
.map(|x| if robots.iter().any(|r| r.pos == (x, y)) { 'X' } else { ' ' })
60+
.collect::<String>()
61+
})
62+
.collect_vec();
63+
64+
if lines.iter().any(|line| regex_is_match!(r"X{10,}", line)) {
65+
for line in lines {
66+
println!("{line}");
67+
}
68+
println!();
69+
true
70+
} else {
71+
false
72+
}
73+
})
74+
.unwrap()
75+
}
76+
77+
#[aoc_main]
78+
fn solve(input: Input) -> impl Into<Solution> {
79+
let robots = input.parse_lines::<Robot>();
80+
81+
(part1(robots.clone(), 101, 103), part2(robots.clone().collect(), 101, 103))
82+
}
83+
84+
#[cfg(test)]
85+
mod tests {
86+
use super::*;
87+
#[test]
88+
fn test_examples() {
89+
let example = "
90+
p=0,4 v=3,-3
91+
p=6,3 v=-1,-3
92+
p=10,3 v=-1,2
93+
p=2,0 v=2,-1
94+
p=0,0 v=1,3
95+
p=3,0 v=-2,-2
96+
p=7,6 v=-1,-3
97+
p=3,0 v=-1,-2
98+
p=9,3 v=2,3
99+
p=7,3 v=-1,2
100+
p=2,4 v=2,-3
101+
p=9,5 v=-3,-3
102+
";
103+
assert_eq!(part1(Input::from(example).parse_lines(), 11, 7), 12);
104+
}
105+
}

0 commit comments

Comments
 (0)