Skip to content

Commit 0648100

Browse files
committed
14th day
1 parent f5078ba commit 0648100

File tree

3 files changed

+154
-0
lines changed

3 files changed

+154
-0
lines changed

data/examples/14.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
p=0,4 v=3,-3
2+
p=6,3 v=-1,-3
3+
p=10,3 v=-1,2
4+
p=2,0 v=2,-1
5+
p=0,0 v=1,3
6+
p=3,0 v=-2,-2
7+
p=7,6 v=-1,-3
8+
p=3,0 v=-1,-2
9+
p=9,3 v=2,3
10+
p=7,3 v=-1,2
11+
p=2,4 v=2,-3
12+
p=9,5 v=-3,-3
13+
14+
EXAMPLE: WIDTH=11 HEIGHT=7

src/bin/14.rs

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
advent_of_code::solution!(14);
2+
3+
use advent_of_code::majcn::math::*;
4+
use advent_of_code::maneatingape::hash::*;
5+
use advent_of_code::maneatingape::iter::*;
6+
use advent_of_code::maneatingape::parse::*;
7+
use advent_of_code::maneatingape::point::*;
8+
9+
struct Robot {
10+
position: Point,
11+
velocity: Point,
12+
}
13+
14+
fn parse_data(input: &str) -> (Vec<Robot>, i32, i32) {
15+
const DEFAULT_WIDTH: i32 = 101;
16+
const DEFAULT_HEIGHT: i32 = 103;
17+
18+
let default_right = format!("{DEFAULT_WIDTH},{DEFAULT_HEIGHT}",);
19+
let (left, right) = input.split_once("\n\n").unwrap_or((input, &default_right));
20+
21+
let robots = left
22+
.iter_signed()
23+
.chunk::<4>()
24+
.map(|[x, y, vx, vy]| Robot {
25+
position: Point::new(x, y),
26+
velocity: Point::new(vx, vy),
27+
})
28+
.collect();
29+
30+
let [width, height] = right.iter_signed().chunk::<2>().next().unwrap();
31+
32+
(robots, width, height)
33+
}
34+
35+
pub fn part_one(input: &str) -> Option<u32> {
36+
let (robots, width, height) = parse_data(input);
37+
38+
let mut robots = robots;
39+
40+
for _ in 0..100 {
41+
for robot in robots.iter_mut() {
42+
robot.position.x = (robot.position.x + robot.velocity.x).modulo(width);
43+
robot.position.y = (robot.position.y + robot.velocity.y).modulo(height);
44+
}
45+
}
46+
47+
let width_center_start = width / 2 + 1;
48+
let width_center_end = width / 2 - 1;
49+
let height_center_start = height / 2 + 1;
50+
let height_center_end = height / 2 - 1;
51+
52+
let mut quadrants = [0; 4];
53+
for robot in robots {
54+
if (0..=width_center_end).contains(&robot.position.x)
55+
&& (0..=height_center_end).contains(&robot.position.y)
56+
{
57+
quadrants[0] += 1;
58+
}
59+
60+
if (0..=width_center_end).contains(&robot.position.x)
61+
&& (height_center_start..height).contains(&robot.position.y)
62+
{
63+
quadrants[1] += 1;
64+
}
65+
66+
if (width_center_start..width).contains(&robot.position.x)
67+
&& (0..=height_center_end).contains(&robot.position.y)
68+
{
69+
quadrants[2] += 1;
70+
}
71+
72+
if (width_center_start..width).contains(&robot.position.x)
73+
&& (height_center_start..height).contains(&robot.position.y)
74+
{
75+
quadrants[3] += 1;
76+
}
77+
}
78+
79+
let result = quadrants.into_iter().product();
80+
81+
Some(result)
82+
}
83+
84+
pub fn part_two(input: &str) -> Option<u32> {
85+
let (robots, width, height) = parse_data(input);
86+
87+
let mut robots = robots;
88+
89+
let mut time = 0;
90+
'outer: loop {
91+
for robot in robots.iter_mut() {
92+
robot.position.x = (robot.position.x + robot.velocity.x).modulo(width);
93+
robot.position.y = (robot.position.y + robot.velocity.y).modulo(height);
94+
}
95+
96+
time += 1;
97+
98+
let mut robots_set = FastSet::with_capacity(robots.len());
99+
for robot in robots.iter() {
100+
if !robots_set.insert(robot.position) {
101+
continue 'outer;
102+
}
103+
}
104+
105+
return Some(time);
106+
}
107+
}
108+
109+
#[cfg(test)]
110+
mod tests {
111+
use super::*;
112+
113+
#[test]
114+
fn test_part_one() {
115+
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
116+
assert_eq!(result, Some(12));
117+
}
118+
119+
#[test]
120+
fn test_part_two() {
121+
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
122+
assert_eq!(result, Some(1));
123+
}
124+
}

src/majcn/math.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
pub trait Modulo<T> {
2+
fn modulo(self, m: T) -> T;
3+
}
4+
5+
impl Modulo<i32> for i32 {
6+
#[inline]
7+
fn modulo(self, m: i32) -> i32 {
8+
let result = self % m;
9+
if result < 0 {
10+
result + m
11+
} else {
12+
result
13+
}
14+
}
15+
}
16+
117
pub trait SumOfNaturalNumbers<T> {
218
fn sum_of_natural_numbers(self) -> T;
319
}

0 commit comments

Comments
 (0)