Skip to content

Commit a758057

Browse files
committed
Day 14
1 parent 86062b2 commit a758057

File tree

4 files changed

+187
-1
lines changed

4 files changed

+187
-1
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ Solutions for [Advent of Code](https://adventofcode.com/) in [Rust](https://www.
2424
| [Day 11](./src/bin/11.rs) | `284.6µs` | `12.8ms` |
2525
| [Day 12](./src/bin/12.rs) | `434.7µs` | `674.6µs` |
2626
| [Day 13](./src/bin/13.rs) | `90.9µs` | `91.8µs` |
27+
| [Day 14](./src/bin/14.rs) | `31.0µs` | `3.6ms` |
2728

28-
**Total: 27.08ms**
29+
**Total: 30.71ms**
2930
<!--- benchmarking table --->
3031

3132
---

data/examples/14.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
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

mygrid/src/direction.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,15 @@ impl Mul<i32> for Direction {
198198
}
199199
}
200200

201+
impl Mul<u32> for Direction {
202+
type Output = Direction;
203+
204+
#[inline]
205+
fn mul(self, rhs: u32) -> Self::Output {
206+
self * (rhs as isize)
207+
}
208+
}
209+
201210
#[cfg(test)]
202211
mod tests {
203212
use super::*;

src/bin/14.rs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
use mygrid::{direction::Direction, grid::Grid, point::Point};
2+
3+
advent_of_code::solution!(14);
4+
5+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
6+
struct Robot {
7+
position: Point,
8+
velocity: Direction,
9+
}
10+
11+
#[derive(Debug, Clone)]
12+
struct Configuration {
13+
seconds: u32,
14+
grid_size: Point,
15+
robots: Vec<Robot>,
16+
}
17+
18+
#[inline]
19+
fn parse_input(input: &str) -> Vec<Robot> {
20+
input
21+
.lines()
22+
.filter(|line| !line.is_empty())
23+
.map(|line| {
24+
let (position, velocity) = line[2..].split_once(" v=").unwrap();
25+
26+
let (px, py) = position.split_once(",").unwrap();
27+
let (vx, vy) = velocity.split_once(",").unwrap();
28+
Robot {
29+
position: Point::new(py.parse().unwrap(), px.parse().unwrap()),
30+
velocity: Direction::new(vy.parse().unwrap(), vx.parse().unwrap()),
31+
}
32+
})
33+
.collect()
34+
}
35+
36+
#[inline]
37+
fn wrap_position(position: Point, grid_size: Point) -> Point {
38+
Point::new(
39+
(position.line % grid_size.line + grid_size.line) % grid_size.line,
40+
(position.column % grid_size.column + grid_size.column) % grid_size.column,
41+
)
42+
}
43+
44+
fn solve_p1(configuration: Configuration) -> u32 {
45+
let result = configuration
46+
.robots
47+
.iter()
48+
.map(|robot| {
49+
let position = robot.position + (robot.velocity * configuration.seconds);
50+
let wrapped_position = wrap_position(position, configuration.grid_size);
51+
wrapped_position
52+
})
53+
.fold((0, 0, 0, 0), |mut acc, position| {
54+
let middle_line = configuration.grid_size.line / 2;
55+
let middle_column = configuration.grid_size.column / 2;
56+
// find out the quadrant of the position
57+
let left = position.line < middle_line;
58+
let right = position.line > middle_line;
59+
let top = position.column < middle_column;
60+
let bottom = position.column > middle_column;
61+
62+
acc.0 += (top && left) as u32;
63+
acc.1 += (bottom && left) as u32;
64+
acc.2 += (top && right) as u32;
65+
acc.3 += (bottom && right) as u32;
66+
acc
67+
});
68+
69+
result.0 * result.1 * result.2 * result.3
70+
}
71+
72+
pub fn part_one(input: &str) -> Option<u32> {
73+
let configuration = Configuration {
74+
seconds: 100,
75+
grid_size: Point::new(103, 101),
76+
robots: parse_input(input),
77+
};
78+
79+
Some(solve_p1(configuration))
80+
}
81+
82+
pub fn part_two(input: &str) -> Option<u32> {
83+
let mut configuration = Configuration {
84+
seconds: 100,
85+
grid_size: Point::new(103, 101),
86+
robots: parse_input(input),
87+
};
88+
89+
let base_dbg_grid = Grid::new(
90+
configuration.grid_size.column as usize,
91+
configuration.grid_size.line as usize,
92+
'.',
93+
);
94+
95+
let mut seconds = 0;
96+
97+
while seconds < 10000 {
98+
let mut dbg_grid = base_dbg_grid.clone();
99+
100+
for robot in configuration.robots.iter_mut() {
101+
let position = robot.position + robot.velocity;
102+
let wrapped_position = wrap_position(position, configuration.grid_size);
103+
robot.position = wrapped_position;
104+
}
105+
seconds += 1;
106+
107+
let robot_on_column_count = configuration
108+
.robots
109+
.iter()
110+
// found visually
111+
.filter(|&r| r.position.column > 24 && r.position.column < 55)
112+
.count();
113+
if robot_on_column_count > 200 {
114+
for robot in configuration.robots.iter() {
115+
dbg_grid[robot.position] = '#';
116+
}
117+
// dbg!(&dbg_grid);
118+
// dbg!(&seconds);
119+
120+
//let mut buffer = String::new();
121+
//std::io::stdin()
122+
// .read_line(&mut buffer)
123+
// .expect("Failed to read line");
124+
125+
// found visually
126+
if seconds == 7083 {
127+
return Some(seconds);
128+
}
129+
}
130+
}
131+
132+
Some(seconds)
133+
}
134+
135+
#[cfg(test)]
136+
mod tests {
137+
use super::*;
138+
139+
#[test]
140+
fn test_one_robot() {
141+
let configuration = Configuration {
142+
seconds: 2,
143+
grid_size: Point::new(7, 11),
144+
robots: vec![Robot {
145+
position: Point::new(4, 2),
146+
velocity: Direction::new(-3, 2),
147+
}],
148+
};
149+
150+
let result = solve_p1(configuration);
151+
assert_eq!(result, 0);
152+
}
153+
154+
#[test]
155+
fn test_part_one() {
156+
let configuration = Configuration {
157+
seconds: 100,
158+
grid_size: Point::new(7, 11),
159+
robots: parse_input(&advent_of_code::template::read_file("examples", DAY)),
160+
};
161+
let result = solve_p1(configuration);
162+
assert_eq!(result, 12);
163+
}
164+
}

0 commit comments

Comments
 (0)