Skip to content

Commit 4b0cf47

Browse files
committed
rust: 2024/14: a, b
1 parent 74aa313 commit 4b0cf47

File tree

3 files changed

+139
-2
lines changed

3 files changed

+139
-2
lines changed

rust/src/main.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ mod utils;
55

66
fn main() {
77
let year = 2024;
8-
let day = 13;
8+
let day = 14;
99
let input = utils::input::get(year, day);
1010
println!(" ----------------------------");
1111
println!(" | AdventOfCode {}/{:0>2} |", year, day);
1212
println!(" ----------------------------");
13-
year2024::day13::solve(&input);
13+
year2024::day14::solve(&input);
1414
}

rust/src/year2024/day14/mod.rs

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
use std::{
2+
collections::HashMap,
3+
io::{self, Stdin},
4+
};
5+
6+
use itertools::Itertools;
7+
use nom::{bytes::complete::tag, character::complete::i64, IResult};
8+
use num_traits::Euclid;
9+
use regex::Regex;
10+
11+
use crate::utils::vec2::Vec2;
12+
13+
extern crate test;
14+
15+
#[bench]
16+
pub fn bench_a(b: &mut test::Bencher) {
17+
let input = crate::utils::input::get(2024, 14);
18+
b.iter(|| solve_a(&input));
19+
}
20+
21+
#[bench]
22+
pub fn bench_b(b: &mut test::Bencher) {
23+
let input = crate::utils::input::get(2024, 14);
24+
b.iter(|| solve_b(&input));
25+
}
26+
27+
#[allow(dead_code)]
28+
pub fn solve(input: &str) {
29+
println!("part a: {}", solve_a(input));
30+
println!("part b: {}", solve_b(input));
31+
}
32+
33+
#[derive(Debug, Clone)]
34+
struct Robot {
35+
pos: Vec2<i64>,
36+
vel: Vec2<i64>,
37+
}
38+
39+
fn parse_robot(line: &str) -> IResult<&str, Robot> {
40+
let (line, _) = tag("p=")(line)?;
41+
let (line, px) = i64(line)?;
42+
let (line, _) = tag(",")(line)?;
43+
let (line, py) = i64(line)?;
44+
let (line, _) = tag(" v=")(line)?;
45+
let (line, vx) = i64(line)?;
46+
let (line, _) = tag(",")(line)?;
47+
let (line, vy) = i64(line)?;
48+
Ok((
49+
line,
50+
Robot {
51+
pos: (px, py).into(),
52+
vel: (vx, vy).into(),
53+
},
54+
))
55+
}
56+
57+
fn parse_robots(input: &str) -> Vec<Robot> {
58+
let mut robots = Vec::new();
59+
for line in input.lines() {
60+
if let Ok((_, robot)) = parse_robot(line) {
61+
robots.push(robot);
62+
} else {
63+
println!("could not parse line");
64+
}
65+
}
66+
robots
67+
}
68+
69+
fn print_bots(botmap: &HashMap<Vec2<i64>, usize>, xmax: i64, ymax: i64) {
70+
for y in 0..ymax {
71+
for x in 0..xmax {
72+
if let Some(count) = botmap.get(&(x, y).into()) {
73+
print!("{}", count.to_string());
74+
} else {
75+
print!("0");
76+
}
77+
}
78+
println!();
79+
}
80+
}
81+
82+
fn safety_score(robots: &Vec<Robot>, xmax: i64, ymax: i64) -> u64 {
83+
let (mut q1, mut q2, mut q3, mut q4) = (0, 0, 0, 0);
84+
for b in robots.iter().map(|b| b.pos) {
85+
let left = b.x < xmax / 2;
86+
let top = b.y < ymax / 2;
87+
let right = b.x >= (xmax + 1) / 2;
88+
let bot = b.y >= (ymax + 1) / 2;
89+
match (left, top, right, bot) {
90+
(true, true, false, false) => q1 += 1,
91+
(false, true, true, false) => q2 += 1,
92+
(true, false, false, true) => q3 += 1,
93+
(false, false, true, true) => q4 += 1,
94+
_ => (),
95+
}
96+
}
97+
q1 * q2 * q3 * q4
98+
}
99+
100+
fn solve_a(input: &str) -> u64 {
101+
println!("{}", input);
102+
let mut robots = parse_robots(input);
103+
let xmax = 101;
104+
let ymax = 103;
105+
let mut botmap: HashMap<Vec2<i64>, usize> = HashMap::new();
106+
for robot in robots.iter_mut() {
107+
robot.pos += robot.vel * 100;
108+
robot.pos.x = robot.pos.x.rem_euclid(xmax);
109+
robot.pos.y = robot.pos.y.rem_euclid(ymax);
110+
*botmap.entry(robot.pos).or_insert(0) += 1;
111+
}
112+
print_bots(&botmap, xmax, ymax);
113+
safety_score(&robots, xmax, ymax)
114+
}
115+
116+
#[allow(dead_code)]
117+
fn solve_b(input: &str) -> u64 {
118+
// the tree should be when most robots gather in one place, which should minimize the
119+
// safety score. another alternative would be to calculate the variance
120+
let mut robots = parse_robots(input);
121+
let xmax = 101;
122+
let ymax = 103;
123+
let mut scores = Vec::new();
124+
for _ in 0..10_000 {
125+
let s = safety_score(&robots, xmax, ymax);
126+
scores.push(s);
127+
let mut botmap: HashMap<Vec2<i64>, usize> = HashMap::new();
128+
for robot in robots.iter_mut() {
129+
robot.pos += robot.vel;
130+
robot.pos.x = robot.pos.x.rem_euclid(xmax);
131+
robot.pos.y = robot.pos.y.rem_euclid(ymax);
132+
*botmap.entry(robot.pos).or_insert(0) += 1;
133+
}
134+
}
135+
scores.iter().position_min().unwrap() as u64
136+
}

rust/src/year2024/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ pub mod day10;
1111
pub mod day11;
1212
pub mod day12;
1313
pub mod day13;
14+
pub mod day14;

0 commit comments

Comments
 (0)