136 lines
3.4 KiB
Rust
136 lines
3.4 KiB
Rust
use std::{
|
|
collections::{HashMap, HashSet},
|
|
thread,
|
|
time::Duration,
|
|
};
|
|
|
|
use advent_of_code_2024::{make_main, next, Pair, SResult};
|
|
use regex::Regex;
|
|
|
|
make_main!();
|
|
|
|
fn solve(lines: Vec<String>) -> SResult<(usize, usize)> {
|
|
// NOTE: this needs to be adjusted for the size of the grid
|
|
let dims = (101, 103);
|
|
let pos_regex = Regex::new(r"p=(?<x>\d+),(?<y>\d+) v=(?<xvel>-?\d+),(?<yvel>-?\d+)").unwrap();
|
|
let mut robots = vec![];
|
|
for line in lines {
|
|
let caps = pos_regex.captures(&line.trim()).unwrap();
|
|
let x = caps["x"].parse::<usize>().unwrap();
|
|
let y = caps["y"].parse::<usize>().unwrap();
|
|
let xvel = caps["xvel"].parse::<i64>().unwrap();
|
|
let yvel = caps["yvel"].parse::<i64>().unwrap();
|
|
robots.push(Robot {
|
|
vel: (xvel, yvel),
|
|
pos: (x, y),
|
|
})
|
|
}
|
|
|
|
// Simulation GO
|
|
// 79, 388, 491, 697, 800, 903, 1006, 1109, 1212, 1315
|
|
let millis = Duration::from_millis(10);
|
|
let mut n = 0;
|
|
let mut tens = 11usize;
|
|
let mut ones = 24usize;
|
|
loop {
|
|
if (n / 100 == tens && n % 100 == ones) || (n >= 800 && (n - 800) % 103 == 0) {
|
|
print!("{}[2J", 27 as char);
|
|
println!("{}", n);
|
|
print_grid(&robots, dims);
|
|
if (n / 100 == tens && n % 100 == ones) {
|
|
tens += 1;
|
|
ones += 1;
|
|
}
|
|
thread::sleep(millis);
|
|
}
|
|
n += 1;
|
|
for robot in robots.iter_mut() {
|
|
robot.advance(dims);
|
|
}
|
|
}
|
|
//Ok((calc_safety(&robots, dims).iter().fold(1, |x, y| x * y), 0))
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
struct Robot {
|
|
vel: Pair<i64>,
|
|
pos: Pair,
|
|
}
|
|
|
|
impl Robot {
|
|
fn advance(&mut self, dims: Pair) {
|
|
self.pos.0 = roll(self.pos.0, self.vel.0, dims.0);
|
|
self.pos.1 = roll(self.pos.1, self.vel.1, dims.1);
|
|
}
|
|
}
|
|
|
|
fn roll(pos: usize, vel: i64, dim: usize) -> usize {
|
|
let ipos = pos as i64;
|
|
if ipos + vel >= 0 {
|
|
((ipos + vel) as usize) % dim
|
|
} else {
|
|
((ipos + vel) + dim as i64) as usize
|
|
}
|
|
}
|
|
|
|
fn calc_safety(robots: &[Robot], dims: Pair) -> [usize; 4] {
|
|
let mut scores = [0usize; 4];
|
|
for robot in robots {
|
|
let xhalf = part(robot.pos.0, dims.0);
|
|
let yhalf = part(robot.pos.1, dims.1);
|
|
match (xhalf, yhalf) {
|
|
(0, 0) => scores[0] += 1,
|
|
(0, 1) => scores[1] += 1,
|
|
(1, 0) => scores[2] += 1,
|
|
(1, 1) => scores[3] += 1,
|
|
_ => {
|
|
// Do nothing; this is expected
|
|
}
|
|
}
|
|
}
|
|
scores
|
|
}
|
|
|
|
fn part(pos: usize, dim: usize) -> usize {
|
|
if pos < dim / 2 {
|
|
0
|
|
} else if pos > dim / 2 {
|
|
1
|
|
} else {
|
|
2
|
|
}
|
|
}
|
|
|
|
fn print_grid(robots: &[Robot], dims: Pair) {
|
|
println!("");
|
|
let mut pos = HashMap::new();
|
|
for rob in robots {
|
|
*pos.entry(rob.pos).or_insert(0) += 1;
|
|
}
|
|
for j in 0..dims.1 {
|
|
for i in 0..dims.0 {
|
|
if let Some(count) = pos.get(&(i, j)) {
|
|
print!("{}", count);
|
|
} else {
|
|
print!(" ");
|
|
}
|
|
}
|
|
println!("");
|
|
}
|
|
println!("");
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use advent_of_code_2024::input;
|
|
|
|
use super::*;
|
|
#[test]
|
|
fn d14p1() {
|
|
return;
|
|
let strings: Vec<String> = input!("d14p1.txt");
|
|
let got = solve(strings).unwrap();
|
|
assert_eq!(got, (12, 0));
|
|
}
|
|
}
|