use regex::Regex; use std::collections::HashSet; fn cycle_add(u: u32, i: i32, limit: u32) -> u32 { let sum: i32 = u as i32 + i; let mut sum_u: u32 = if sum < 0 { sum + limit as i32 } else { sum } as u32; while sum_u >= limit { sum_u -= limit; } sum_u } #[derive(Debug)] struct Robot { p: (u32, u32), v: (i32, i32), } impl Robot { fn parse(input: &str) -> Vec { let mut result: Vec<_> = vec![]; let re = Regex::new(r"p=([0-9]+),([0-9]+) v=([0-9-]+),([0-9-]+)").unwrap(); for (_, [px, py, vx, vy]) in re.captures_iter(input).map(|c| c.extract()) { result.push(Robot { p: (px.parse().unwrap(), py.parse().unwrap()), v: (vx.parse().unwrap(), vy.parse().unwrap()), }); } // println!("Result: {result:?}"); result } fn step(&mut self, (lx, ly): (u32, u32)) { let p: &mut (u32, u32) = &mut self.p; let v = self.v; p.0 = cycle_add(p.0, v.0, lx); p.1 = cycle_add(p.1, v.1, ly); } } struct Bathroom { robots: Vec, limit: (u32, u32), } impl Bathroom { fn step(&mut self) { for r in self.robots.iter_mut() { r.step(self.limit); } } fn stepn(&mut self, seconds: u32) { for _i in 0..seconds { self.step(); } } fn quadrant(&self, Robot { p: (px, py), .. }: &Robot) -> Option { let (lx, ly) = self.limit; let (hx, hy) = (lx / 2, ly / 2); if *px == hx || *py == hy { None } else { Some(if *px < hx { 0 } else { 1 } + if *py < hy { 0 } else { 2 }) } } fn safety(&self) -> u32 { let mut scores = [0; 4]; for r in self.robots.iter() { if let Some(q) = self.quadrant(r) { scores[q] += 1; } } scores.iter().product() } fn show(&self) { let positions: HashSet<(u32, u32)> = self.robots.iter().map(|r| r.p).collect(); for i in 0..self.limit.1 { for j in 0..self.limit.0 { print!( "{}", if positions.contains(&(i, j)) { "X" } else { "." } ); } println!(); } } } fn p1(input: &str) -> String { let robots: Vec = Robot::parse(input); let mut bathroom: Bathroom = Bathroom { robots, limit: (101, 103), }; bathroom.stepn(100); dbg!(&bathroom.robots); let result = bathroom.safety(); result.to_string() } // use std::thread::sleep; // use std::time::Duration; fn p2(input: &str) -> String { let robots: Vec = Robot::parse(input); let mut bathroom: Bathroom = Bathroom { robots, limit: (101, 103), }; bathroom.show(); for i in 1.. { println!("\n\nAfter {} seconds:", i); bathroom.step(); bathroom.show(); // sleep(Duration::from_millis(200)); } unreachable!(); } fn main() { aoc2024::run_day("14", p1, p2); }