adventofcode/days/2024/14.rs

162 Zeilen
4,4 KiB
Rust

2024-12-15 13:22:03 +01:00
use advent_of_code::{
strings::{convert_to_array, parsenumber},
Kartesian, Velocity, KD,
};
use advent_of_code_macros::include_aoc;
2024-12-15 13:22:03 +01:00
include_aoc!(2024, 14);
2024-12-15 13:22:03 +01:00
fn parse_robot(line: &str) -> (Kartesian<u32>, Velocity<u32>) {
let mut dir = KD::None;
let mut x = 0;
let mut y = 0;
let mut position = Kartesian::default();
for part in line.splitn(2, ' ') {
match part.get(0..2).unwrap_or("") {
"p=" => {
let (y, x) = part.get(2..).unwrap().split_once(',').unwrap();
position.x = parsenumber(x);
position.y = parsenumber(y);
},
"v=" => {
let (ys, xs) = part.get(2..).unwrap().split_once(',').unwrap();
x = parsenumber(xs);
y = parsenumber(ys);
dir = if xs.get(0..1).unwrap() == "-" && x != 0 {
dir.up()
} else if x > 0 {
dir.down()
} else {
dir
};
dir = if ys.get(0..1).unwrap() == "-" && y != 0 {
dir.left()
} else if x > 0 {
dir.right()
} else {
dir
};
},
_ => {},
}
}
(position, Velocity::new(x, y, dir))
}
fn get_end_start(v: u32) -> (u32, u32) {
match v % 2 {
0 => (v / 2, v / 2),
1 => ((v - 1) / 2 - 1, (v + 1) / 2),
_ => unreachable!(),
}
}
fn calc_safety(coords: Vec<Kartesian<u32>>, space: Kartesian<u32>) -> (u32, u32, u32, u32) {
let mut robots = (0, 0, 0, 0);
let (x_end, x_start) = get_end_start(space.x);
let (y_end, y_start) = get_end_start(space.y);
for robot in coords {
if robot.x <= x_end && robot.y <= y_end {
robots.0 += 1;
} else if robot.x <= x_end && robot.y >= y_start {
robots.1 += 1
} else if robot.x >= x_start && robot.y <= y_end {
robots.2 += 1
} else if robot.x >= x_start && robot.y >= y_start {
robots.3 += 1
} else {
println!("Robot outside of quarts {}:", robot);
println!("1. {}..={}:{}..={}", 0, x_end, 0, y_end);
println!("2. {}..={}:{}..={}", 0, x_end, y_start, space.y - 1);
println!("3. {}..={}:{}..={}", x_start, space.x - 1, 0, y_end);
println!("4. {}..={}:{}..={}", x_start, space.x - 1, y_start, space.y - 1);
}
}
println!("Robot in quarts: {}, {}, {}, {}", robots.0, robots.1, robots.2, robots.3);
robots
}
fn calc_final(r: (u32, u32, u32, u32)) -> u32 {
r.0 * r.1 * r.2 * r.3
}
fn main() {
const SPACE: Kartesian<u32> = Kartesian::new(103, 101);
let mut target_coords = Vec::new();
let robots = convert_to_array::<_, _, '\n'>(DATA, parse_robot);
for (mut position, velocity) in robots {
for _i in 0..100 {
position = position.wrapping_move_velocity(velocity, SPACE);
}
target_coords.push(position);
}
println!("{:?}", target_coords);
println!("Safety Factor: {}", calc_final(calc_safety(target_coords, SPACE)));
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_start_end() {
assert_eq!(get_end_start(7), (2, 4))
}
#[test]
fn test_safety() {
let positions = vec![
Kartesian {
x: 5,
y: 3,
},
Kartesian {
x: 4,
y: 5,
},
Kartesian {
x: 0,
y: 9,
},
Kartesian {
x: 5,
y: 4,
},
Kartesian {
x: 6,
y: 1,
},
Kartesian {
x: 3,
y: 1,
},
Kartesian {
x: 0,
y: 6,
},
Kartesian {
x: 3,
y: 2,
},
Kartesian {
x: 2,
y: 0,
},
Kartesian {
x: 0,
y: 6,
},
Kartesian {
x: 5,
y: 4,
},
Kartesian {
x: 6,
y: 6,
},
2024-12-15 13:22:03 +01:00
];
assert_eq!(calc_safety(positions, Kartesian::new(7, 11)), (1, 3, 4, 1));
}
}