if let Some(Ok(line1)) = iter.next() {
let a_cap = button_a.captures(&line1).unwrap();
let a_factors = Vector2::new(
- a_cap.get(1).unwrap().as_str().parse::<i64>().unwrap(),
- a_cap.get(2).unwrap().as_str().parse::<i64>().unwrap(),
+ a_cap[1].parse::<i64>().unwrap(),
+ a_cap[2].parse::<i64>().unwrap(),
);
let line2 = iter.next().unwrap().unwrap();
let b_cap = button_b.captures(&line2).unwrap();
let b_factors = Vector2::new(
- b_cap.get(1).unwrap().as_str().parse::<i64>().unwrap(),
- b_cap.get(2).unwrap().as_str().parse::<i64>().unwrap(),
+ b_cap[1].parse::<i64>().unwrap(),
+ b_cap[2].parse::<i64>().unwrap(),
);
let line3 = iter.next().unwrap().unwrap();
let prize_cap = prize.captures(&line3).unwrap();
let prize_xy = Vector2::new(
- prize_cap.get(1).unwrap().as_str().parse::<i64>().unwrap(),
- prize_cap.get(2).unwrap().as_str().parse::<i64>().unwrap(),
+ prize_cap[1].parse::<i64>().unwrap(),
+ prize_cap[2].parse::<i64>().unwrap(),
);
let _ = iter.next();
equations.push((a_factors, b_factors, prize_xy));
--- /dev/null
+use std::io::BufRead;
+
+use nalgebra::{DMatrix, Point2, Vector2};
+use regex::Regex;
+
+type Position = Point2<i64>;
+type Velocity = Vector2<i64>;
+
+pub fn read(reader: &mut dyn BufRead) -> Vec<(Position, Velocity)> {
+ let regex_line = { Regex::new(r#"([+-]?\d+),([+-]?\d+).*?([+-]?\d+),([+-]?\d+)"#).unwrap() };
+
+ reader
+ .lines()
+ .map(|l| {
+ let l = l.unwrap();
+ let captures = regex_line.captures(&l).unwrap();
+ (
+ Position::new(
+ captures[1].parse::<i64>().unwrap(),
+ captures[2].parse::<i64>().unwrap(),
+ ),
+ Velocity::new(
+ captures[3].parse::<i64>().unwrap(),
+ captures[4].parse::<i64>().unwrap(),
+ ),
+ )
+ })
+ .collect()
+}
+
+fn robot_positions<'a>(
+ robots: &'a [(Position, Velocity)],
+ area_size: (i64, i64),
+ seconds: i64,
+) -> impl Iterator<Item = (i64, i64)> + use<'a> {
+ robots.into_iter().map(move |(pos, vel)| {
+ let pos = pos + vel * seconds;
+ (
+ pos[0].rem_euclid(area_size.0),
+ pos[1].rem_euclid(area_size.1),
+ )
+ })
+}
+
+pub fn safety_factor(robots: &[(Position, Velocity)], area_size: (i64, i64), seconds: i64) -> u32 {
+ let quadrants = robot_positions(robots, area_size, seconds).fold(
+ (0, 0, 0, 0),
+ |(q1, q2, q3, q4), (x, y)| {
+ if x > area_size.0 / 2 {
+ if y < area_size.1 / 2 {
+ return (q1 + 1, q2, q3, q4);
+ } else if y > area_size.1 / 2 {
+ return (q1, q2, q3, q4 + 1);
+ }
+ } else if x < area_size.0 / 2 {
+ if y < area_size.1 / 2 {
+ return (q1, q2 + 1, q3, q4);
+ } else if y > area_size.1 / 2 {
+ return (q1, q2, q3 + 1, q4);
+ }
+ }
+ (q1, q2, q3, q4)
+ },
+ );
+ quadrants.0 * quadrants.1 * quadrants.2 * quadrants.3
+}
+
+pub fn format_robots(
+ robots: &[(Position, Velocity)],
+ area_size: (i64, i64),
+ seconds: i64,
+) -> String {
+ let mut area = DMatrix::<u32>::repeat(area_size.1 as usize, area_size.0 as usize, 0);
+ for (x, y) in robot_positions(robots, area_size, seconds) {
+ area[(y as usize, x as usize)] += 1;
+ }
+ let mut str = String::new();
+ for i in 0..area.nrows() {
+ for j in 0..area.ncols() {
+ let n = area[(i, j)];
+ if n > 0 {
+ str.push('#');
+ } else {
+ str.push(' ');
+ }
+ }
+ str.push('\n');
+ }
+ str
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ static POSITIONS_AND_VELOCITIES: &str = "p=0,4 v=3,-3
+p=6,3 v=-1,-3
+p=10,3 v=-1,2
+p=2,0 v=2,-1
+p=0,0 v=1,3
+p=3,0 v=-2,-2
+p=7,6 v=-1,-3
+p=3,0 v=-1,-2
+p=9,3 v=2,3
+p=7,3 v=-1,2
+p=2,4 v=2,-3
+p=9,5 v=-3,-3";
+
+ #[test]
+ fn part1() {
+ let robots = read(&mut POSITIONS_AND_VELOCITIES.as_bytes());
+ assert_eq!(safety_factor(&robots, (11, 7), 100), 12);
+ }
+}