Skip to content

Commit 3b5690a

Browse files
committed
[2024] Cleanup day 14
1 parent eff9739 commit 3b5690a

File tree

1 file changed

+42
-68
lines changed

1 file changed

+42
-68
lines changed

aoc_2024/src/day_14.rs

Lines changed: 42 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,78 @@
1-
use std::io::stdin;
2-
31
use common::{solution, Answer};
4-
use itertools::Itertools;
52
use nd_vec::{vector, Vec2};
63

74
solution!("Restroom Redoubt", 14);
85

6+
// Part A was easy enough, just implement the logic and run it for 100 ticks. To
7+
// be more efferent, instead of adding the velocity to the position of each
8+
// robot on each tick, you can just add vel * ticks then basically modulo to put
9+
// it back in bounds.
910
fn part_a(input: &str) -> Answer {
1011
let mut problem = Problem::parse(input);
11-
12-
// println!();
13-
for _ in 0..100 {
14-
problem.tick();
15-
}
16-
// problem.debug();
12+
problem.tick(100);
1713
problem.score().into()
1814
}
1915

16+
// When I read todays part B, I was just so confused for a while. To find boards
17+
// that were likely showing some pattern, I just sum the distances from each
18+
// robot to the board center, when this drops below a set threshold, I assume
19+
// that is the tree. You can uncomment the .debug() call to actually see the
20+
// tree.
2021
fn part_b(input: &str) -> Answer {
2122
let mut problem = Problem::parse(input);
2223

23-
// println!();
24-
for i in 0..10_000 {
25-
problem.tick();
26-
// println!("{} v", i + 1);
27-
// problem.debug();
28-
// println!();
29-
// println!("{}", problem.total_distance());
30-
31-
if problem.total_distance() < 6_000_000 {
32-
println!("{}", problem.total_distance());
33-
println!("{} v", i + 1);
34-
problem.debug();
35-
stdin().read_line(&mut String::new());
24+
for i in 0.. {
25+
problem.tick(1);
26+
if problem.total_distance() < 20_000 {
27+
// problem.debug();
28+
return (i + 1).into();
3629
}
3730
}
38-
// problem.debug();
39-
problem.score().into()
31+
32+
unreachable!()
4033
}
4134

42-
// rename
43-
#[derive(Debug)]
4435
struct Problem {
4536
bounds: Vec2<i32>,
4637
robots: Vec<Robot>,
4738
}
4839

49-
#[derive(Debug)]
5040
struct Robot {
5141
pos: Vec2<i32>,
5242
vel: Vec2<i32>,
5343
}
5444

5545
impl Problem {
5646
fn parse(input: &str) -> Self {
57-
let robots = input.lines().map(|x| Robot::parse(x)).collect::<Vec<_>>();
47+
let robots = input.lines().map(Robot::parse).collect::<Vec<_>>();
5848

5949
let mut bounds = vector!(0, 0);
60-
for robot in robots.iter() {
61-
bounds = vector!(robot.pos.x().max(bounds.x()), robot.pos.y().max(bounds.y()));
62-
}
63-
bounds += vector!(1, 1);
50+
robots.iter().for_each(|robot| {
51+
bounds = vector!(robot.pos.x().max(bounds.x()), robot.pos.y().max(bounds.y()))
52+
});
6453

65-
Self { robots, bounds }
54+
Self {
55+
robots,
56+
bounds: bounds + vector!(1, 1),
57+
}
6658
}
6759

68-
fn tick(&mut self) {
69-
self.robots.iter_mut().for_each(|x| x.tick(self.bounds));
60+
fn tick(&mut self, n: i32) {
61+
self.robots.iter_mut().for_each(|x| x.tick(self.bounds, n));
7062
}
7163

7264
fn total_distance(&self) -> i32 {
73-
let mut sum = 0;
74-
for (a, b) in self.robots.iter().tuple_combinations() {
75-
sum += a.pos.manhattan_distance(&b.pos);
76-
}
77-
sum
65+
let middle = self.bounds / 2;
66+
self.robots
67+
.iter()
68+
.map(|x| x.pos.manhattan_distance(&middle))
69+
.sum()
7870
}
7971

72+
#[allow(unused)]
8073
fn debug(&self) {
81-
let half_bounds = self.bounds / 2;
82-
83-
for y in (0..self.bounds.y()) {
84-
for x in (0..self.bounds.x()) {
74+
for y in 0..self.bounds.y() {
75+
for x in 0..self.bounds.x() {
8576
let robots = self
8677
.robots
8778
.iter()
@@ -101,19 +92,14 @@ impl Problem {
10192
fn score(&self) -> u32 {
10293
let half_bounds = self.bounds / 2;
10394

104-
// 0 1 2 3 4
105-
10695
let mut quadrants = [0; 4];
107-
for robot in self.robots.iter() {
108-
let pos = robot.pos;
109-
96+
for pos in self.robots.iter().map(|x| x.pos) {
11097
if pos.x() == half_bounds.x() || pos.y() == half_bounds.y() {
11198
continue;
11299
}
113100

114101
let width = (0..=half_bounds.x()).contains(&pos.x());
115102
let height = (0..=half_bounds.y()).contains(&pos.y());
116-
117103
quadrants[((width as usize) << 1) | height as usize] += 1;
118104
}
119105

@@ -135,24 +121,12 @@ impl Robot {
135121
}
136122
}
137123

138-
fn tick(&mut self, bounds: Vec2<i32>) {
139-
self.pos += self.vel;
140-
141-
while self.pos.x() < 0 {
142-
self.pos += vector!(bounds.x(), 0);
143-
}
144-
145-
while self.pos.x() >= bounds.x() {
146-
self.pos -= vector!(bounds.x(), 0);
147-
}
148-
149-
while self.pos.y() < 0 {
150-
self.pos += vector!(0, bounds.y());
151-
}
152-
153-
while self.pos.y() >= bounds.y() {
154-
self.pos -= vector!(0, bounds.y());
155-
}
124+
fn tick(&mut self, bounds: Vec2<i32>, n: i32) {
125+
self.pos += self.vel * n;
126+
self.pos = vector!(
127+
(self.pos.x() % bounds.x() + bounds.x()) % bounds.x(),
128+
(self.pos.y() % bounds.y() + bounds.y()) % bounds.y()
129+
);
156130
}
157131
}
158132

0 commit comments

Comments
 (0)