Untitled

 avatar
unknown
rust
4 months ago
3.2 kB
22
Indexable
const ORDERING: [Ordering; 2] = [Ordering::Less, Ordering::Greater];

pub fn solution(test: bool) -> ((usize, Duration), (usize, Duration)) {
    let lines;
    if test {
        lines = include_str!("../../../AdventOfCodeInputs/problem_inputs_2024/day_14_test.txt");
    } else {
        lines = include_str!("../../../AdventOfCodeInputs/problem_inputs_2024/day_14.txt");
    }
    let room = Room::from_str(&lines);
    (solve01(&room), solve02(&room))
}

fn solve01(room: &Room) -> (usize, Duration) {
    let mut room = room.clone();
    let now = Instant::now();
    for _ in 0..100 {
        room.step();
    }
    (room.calc_safety() as usize, now.elapsed())
}

fn solve02(room: &Room) -> (usize, Duration) {
    let mut room = room.clone();
    let now = Instant::now();
    let step = (0..room.bounds.0 * room.bounds.1)
        .map(|_| {
            let safety = room.calc_safety();
            room.step();
            safety
        })
        .enumerate()
        .min_by_key(|(step, factor)| *factor)
        .unwrap();
    (step.0 as usize, now.elapsed())
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Robot {
    position: (isize, isize),
    velocity: (isize, isize),
}

impl Robot {
    fn from_str(s: &str) -> Self {
        let mut s = s.split(' ');
        let position = parse_vector(&mut s);
        let velocity = parse_vector(&mut s);
        Self { position, velocity }
    }

    fn step(&mut self, bounds: (isize, isize)) {
        self.position.0 += self.velocity.0;
        self.position.1 += self.velocity.1;
        self.position.0 = self.position.0.rem_euclid(bounds.0 + 1);
        self.position.1 = self.position.1.rem_euclid(bounds.1 + 1);
    }
}

#[derive(Debug, Clone)]
struct Room {
    robots: Vec<Robot>,
    bounds: (isize, isize),
}

impl Room {
    fn from_str(s: &str) -> Self {
        let robots = s.lines().map(Robot::from_str).collect_vec();
        let bounds = robots.iter().fold((0, 0), |acc, robot| {
            (acc.0.max(robot.position.0), acc.1.max(robot.position.1))
        });
        Self { robots, bounds }
    }

    fn step(&mut self) {
        for robot in &mut self.robots {
            robot.step(self.bounds);
        }
    }

    fn calc_safety(&self) -> usize {
        let mut counts = [0; 4];
        for (i, (order_x, order_y)) in ORDERING
            .iter()
            .cartesian_product(ORDERING.iter())
            .enumerate()
        {
            counts[i] = self
                .robots
                .iter()
                .filter(|robot| {
                    robot.position.0.cmp(&(self.bounds.0 / 2)) == *order_x
                        && robot.position.1.cmp(&(self.bounds.1 / 2)) == *order_y
                })
                .count();
        }
        counts.iter().product()
    }

    fn check_if_tree(&self) -> bool {
        self.robots
            .iter()
            .permutations(2)
            .all(|r| r[0].velocity != r[1].velocity)
    }
}

fn parse_vector(s: &mut std::str::Split<'_, char>) -> (isize, isize) {
    let vector = s
        .next()
        .unwrap()
        .split('=')
        .nth(1)
        .unwrap()
        .split(',')
        .map(|x| x.parse().unwrap())
        .collect_tuple()
        .unwrap();
    vector
}
Editor is loading...
Leave a Comment