101 lines
2.8 KiB
Rust
101 lines
2.8 KiB
Rust
use glam::IVec2;
|
|
use regex::Regex;
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
|
struct Robot {
|
|
position: IVec2,
|
|
velocity: IVec2,
|
|
}
|
|
|
|
#[rustfmt::skip]
|
|
fn parse(input: &str) -> Vec<Robot> {
|
|
let re = Regex::new(r"-?\d+").unwrap();
|
|
input.lines().map(|l| {
|
|
let mut captures = re.captures_iter(l);
|
|
Robot {
|
|
position: IVec2 {
|
|
x: captures.next().unwrap().get(0).unwrap().as_str().parse().unwrap(),
|
|
y: captures.next().unwrap().get(0).unwrap().as_str().parse().unwrap(),
|
|
},
|
|
velocity: IVec2 {
|
|
x: captures.next().unwrap().get(0).unwrap().as_str().parse().unwrap(),
|
|
y: captures.next().unwrap().get(0).unwrap().as_str().parse().unwrap(),
|
|
}
|
|
}
|
|
}).collect()
|
|
}
|
|
|
|
fn get_pos_after_steps(robot: &Robot, steps: &i32, dimensions: &IVec2) -> IVec2 {
|
|
(robot.position + steps * robot.velocity).rem_euclid(*dimensions)
|
|
}
|
|
|
|
fn part1(input: &[Robot], dimensions: &IVec2) -> usize {
|
|
input
|
|
.iter()
|
|
.fold([0, 0, 0, 0], |mut acc, curr| {
|
|
let p = get_pos_after_steps(curr, &100, dimensions);
|
|
if p.x < (dimensions.x / 2) && p.y < (dimensions.y / 2) {
|
|
acc[0] += 1;
|
|
}
|
|
if p.x > (dimensions.x / 2) && p.y < (dimensions.y / 2) {
|
|
acc[1] += 1;
|
|
}
|
|
if p.x < (dimensions.x / 2) && p.y > (dimensions.y / 2) {
|
|
acc[2] += 1
|
|
}
|
|
if p.x > (dimensions.x / 2) && p.y > (dimensions.y / 2) {
|
|
acc[3] += 1;
|
|
}
|
|
acc
|
|
})
|
|
.iter()
|
|
.product()
|
|
}
|
|
|
|
fn print_map(robots: &[Robot], dimensions: &IVec2) -> String {
|
|
let mut res = String::new();
|
|
for y in 0..dimensions.x {
|
|
for x in 0..dimensions.y {
|
|
if robots
|
|
.iter()
|
|
.map(|r| (r.position.x, r.position.y))
|
|
.any(|p| p == (x, y))
|
|
{
|
|
res.push('#');
|
|
} else {
|
|
res.push(' ');
|
|
}
|
|
}
|
|
res.push('\n');
|
|
}
|
|
res
|
|
}
|
|
|
|
fn has_tree(robots: &[Robot]) -> bool {
|
|
let check: Vec<_> = (0..16).map(|i| IVec2::new(i, 0)).collect();
|
|
robots.iter().any(|p| {
|
|
check
|
|
.iter()
|
|
.all(|c| robots.iter().any(|p2| p2.position == p.position + c))
|
|
})
|
|
}
|
|
|
|
fn part2(robots: &mut [Robot], dimensions: &IVec2) -> i32 {
|
|
for i in 0.. {
|
|
if has_tree(robots) {
|
|
eprintln!("{}", print_map(robots, dimensions));
|
|
return i;
|
|
}
|
|
robots
|
|
.iter_mut()
|
|
.for_each(|r| r.position = get_pos_after_steps(r, &1, dimensions))
|
|
}
|
|
unreachable!()
|
|
}
|
|
|
|
fn main() {
|
|
let mut input = parse(include_str!("../input.txt"));
|
|
println!("{}", part1(&input, &IVec2::new(101, 103)));
|
|
println!("{}", part2(&mut input, &IVec2::new(101, 103)));
|
|
}
|