Skip to content

Commit eff9739

Browse files
committed
[2024] Day 14 initial solution
what was part b... ong
1 parent 78598a2 commit eff9739

File tree

3 files changed

+185
-0
lines changed

3 files changed

+185
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Thank you to [Eric Wastl](http://was.tl) for running this incredible yearly even
1818
- [Day 11: Plutonian Pebbles](aoc_2024/src/day_11.rs)
1919
- [Day 12: Garden Groups](aoc_2024/src/day_12.rs)
2020
- [Day 13: Claw Contraption](aoc_2024/src/day_13.rs)
21+
- [Day 14: Restroom Redoubt](aoc_2024/src/day_14.rs)
2122
<!-- MARKER -->
2223

2324
## [2023](https://adventofcode.com/2023) [![aoc_2023](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2023.yml/badge.svg)](https://github.com/connorslade/advent-of-code/actions/workflows/aoc_2023.yml)

aoc_2024/src/day_14.rs

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
use std::io::stdin;
2+
3+
use common::{solution, Answer};
4+
use itertools::Itertools;
5+
use nd_vec::{vector, Vec2};
6+
7+
solution!("Restroom Redoubt", 14);
8+
9+
fn part_a(input: &str) -> Answer {
10+
let mut problem = Problem::parse(input);
11+
12+
// println!();
13+
for _ in 0..100 {
14+
problem.tick();
15+
}
16+
// problem.debug();
17+
problem.score().into()
18+
}
19+
20+
fn part_b(input: &str) -> Answer {
21+
let mut problem = Problem::parse(input);
22+
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());
36+
}
37+
}
38+
// problem.debug();
39+
problem.score().into()
40+
}
41+
42+
// rename
43+
#[derive(Debug)]
44+
struct Problem {
45+
bounds: Vec2<i32>,
46+
robots: Vec<Robot>,
47+
}
48+
49+
#[derive(Debug)]
50+
struct Robot {
51+
pos: Vec2<i32>,
52+
vel: Vec2<i32>,
53+
}
54+
55+
impl Problem {
56+
fn parse(input: &str) -> Self {
57+
let robots = input.lines().map(|x| Robot::parse(x)).collect::<Vec<_>>();
58+
59+
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);
64+
65+
Self { robots, bounds }
66+
}
67+
68+
fn tick(&mut self) {
69+
self.robots.iter_mut().for_each(|x| x.tick(self.bounds));
70+
}
71+
72+
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
78+
}
79+
80+
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()) {
85+
let robots = self
86+
.robots
87+
.iter()
88+
.filter(|r| r.pos == vector!(x, y))
89+
.count();
90+
91+
if robots == 0 {
92+
print!(".");
93+
} else {
94+
print!("{robots}");
95+
}
96+
}
97+
println!();
98+
}
99+
}
100+
101+
fn score(&self) -> u32 {
102+
let half_bounds = self.bounds / 2;
103+
104+
// 0 1 2 3 4
105+
106+
let mut quadrants = [0; 4];
107+
for robot in self.robots.iter() {
108+
let pos = robot.pos;
109+
110+
if pos.x() == half_bounds.x() || pos.y() == half_bounds.y() {
111+
continue;
112+
}
113+
114+
let width = (0..=half_bounds.x()).contains(&pos.x());
115+
let height = (0..=half_bounds.y()).contains(&pos.y());
116+
117+
quadrants[((width as usize) << 1) | height as usize] += 1;
118+
}
119+
120+
quadrants.iter().product()
121+
}
122+
}
123+
124+
impl Robot {
125+
fn parse(input: &str) -> Self {
126+
let (p, v) = input.split_once(" ").unwrap();
127+
let parse_coord = |string: &str| {
128+
let (x, y) = string[2..].split_once(',').unwrap();
129+
vector!(x.parse().unwrap(), y.parse().unwrap())
130+
};
131+
132+
Self {
133+
pos: parse_coord(p),
134+
vel: parse_coord(v),
135+
}
136+
}
137+
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+
}
156+
}
157+
}
158+
159+
#[cfg(test)]
160+
mod test {
161+
use indoc::indoc;
162+
163+
const CASE: &str = indoc! {"
164+
p=0,4 v=3,-3
165+
p=6,3 v=-1,-3
166+
p=10,3 v=-1,2
167+
p=2,0 v=2,-1
168+
p=0,0 v=1,3
169+
p=3,0 v=-2,-2
170+
p=7,6 v=-1,-3
171+
p=3,0 v=-1,-2
172+
p=9,3 v=2,3
173+
p=7,3 v=-1,2
174+
p=2,4 v=2,-3
175+
p=9,5 v=-3,-3
176+
"};
177+
178+
#[test]
179+
fn part_a() {
180+
assert_eq!(super::part_a(CASE), 12.into());
181+
}
182+
}

aoc_2024/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ mod day_10;
1313
mod day_11;
1414
mod day_12;
1515
mod day_13;
16+
mod day_14;
1617
// [import_marker]
1718

1819
pub const SOLUTIONS: &[Solution] = &[
@@ -29,5 +30,6 @@ pub const SOLUTIONS: &[Solution] = &[
2930
day_11::SOLUTION,
3031
day_12::SOLUTION,
3132
day_13::SOLUTION,
33+
day_14::SOLUTION,
3234
// [list_marker]
3335
];

0 commit comments

Comments
 (0)