use crate::utils; extern crate regex; use regex::Regex; pub fn task1() { let input = utils::read_file("input/day23.txt"); let regex = Regex::new(r"^pos=<(?P-?\d+),(?P-?\d+),(?P-?\d+)>, r=(?P\d+)$").unwrap(); let bots: Vec = input .lines() .map(|line| { let m = regex.captures(line).unwrap(); let x = m["x"].parse::().unwrap(); let y = m["y"].parse::().unwrap(); let z = m["z"].parse::().unwrap(); let range = m["range"].parse::().unwrap(); Bot { x, y, z, range } }) .collect(); let big_bot = bots.iter().max_by_key(|it| it.range).unwrap(); println!("The bot with largest range is {:?}", big_bot); let bots_in_range = bots .iter() .filter(|other| big_bot.distance(other) <= big_bot.range) .count(); println!("There are {} bots in range of the big bot.", bots_in_range); } pub fn task2() { let input = utils::read_file("input/day23.txt"); let regex = Regex::new(r"^pos=<(?P-?\d+),(?P-?\d+),(?P-?\d+)>, r=(?P\d+)$").unwrap(); let bots: Vec = input .lines() .map(|line| { let m = regex.captures(line).unwrap(); let x = m["x"].parse::().unwrap(); let y = m["y"].parse::().unwrap(); let z = m["z"].parse::().unwrap(); let range = m["range"].parse::().unwrap(); Bot { x, y, z, range } }) .collect(); // let r_min = bots.iter().min_by_key(|it| it.range).unwrap().range; // let r_max = bots.iter().max_by_key(|it| it.range).unwrap().range; // println!("Radius min max: {}/{}", r_min, r_max); // let x_min = bots.iter().min_by_key(|it| it.x).unwrap().x; // let x_max = bots.iter().max_by_key(|it| it.x).unwrap().x; // println!("X range: {}", x_max - x_min); // let y_min = bots.iter().min_by_key(|it| it.y).unwrap().y; // let y_max = bots.iter().max_by_key(|it| it.y).unwrap().y; // println!("Y range: {}", y_max - y_min); // let z_min = bots.iter().min_by_key(|it| it.z).unwrap().z; // let z_max = bots.iter().max_by_key(|it| it.z).unwrap().z; // println!("Z range: {}", z_max - z_min); let neighbor_counts: Vec<(Bot, usize)> = bots .iter() .flat_map(|bot| bot.corners()) .map(|corner| { let count = bots .iter() .filter(|bot| bot.distance(&corner) <= bot.range) .count(); (corner, count) }) .collect(); let max = neighbor_counts.iter().max_by_key(|it| it.1).unwrap().1; let start = Bot { x: 0, y: 0, z: 0, range: 0, }; let candidates = neighbor_counts.iter().filter(|it| it.1 == max).count(); println!("{} points in range of {} bots", candidates, max); let candidate = neighbor_counts .iter() .filter(|it| it.1 == max) .min_by_key(|it| it.0.distance(&start)); println!( "Corner with most bots in range: {:?}", candidate.unwrap().0.distance(&start) ); // wrong: 37446460,43177892,57318660; 137943012; 102224079; } #[derive(Debug)] struct Bot { x: isize, y: isize, z: isize, range: usize, } impl Bot { fn distance(&self, other: &Self) -> usize { ((other.x - self.x).abs() + (other.y - self.y).abs() + (other.z - self.z).abs()) as usize } fn corners(&self) -> Vec { vec![ Bot { x: self.x + self.range as isize, y: self.y, z: self.z, range: 0, }, Bot { x: self.x - self.range as isize, y: self.y, z: self.z, range: 0, }, Bot { x: self.x, y: self.y + self.range as isize, z: self.z, range: 0, }, Bot { x: self.x, y: self.y - self.range as isize, z: self.z, range: 0, }, Bot { x: self.x, y: self.y, z: self.z + self.range as isize, range: 0, }, Bot { x: self.x, y: self.y, z: self.z - self.range as isize, range: 0, }, ] } }