Day 14: Restroom Redoubt

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://topaz.github.io/paste/ if you prefer sending it through a URL

FAQ

  • Gobbel2000@programming.dev
    link
    fedilink
    arrow-up
    2
    ·
    12 days ago

    Rust

    Part 2 was very surprising in that it had a very vague requirement: “Find christmas tree!”. But my idea of finding the first round where no robots overlap turned out to just work when printing the map, so that was nice. I’m glad I did not instead start looking for symmetric patterns, because the christmas tree map is not symmetric at all.

    Solution
    use euclid::default::*;
    use regex::Regex;
    
    fn parse(input: &str) -> Vec<(Point2D<i32>, Vector2D<i32>)> {
        let re = Regex::new(r"p=(\d+),(\d+) v=(-?\d+),(-?\d+)").unwrap();
        re.captures_iter(input)
            .map(|cap| {
                let (_, [p0, p1, v0, v1]) = cap.extract();
                (
                    Point2D::new(p0.parse().unwrap(), p1.parse().unwrap()),
                    Vector2D::new(v0.parse().unwrap(), v1.parse().unwrap()),
                )
            })
            .collect()
    }
    
    const ROOM: Size2D<i32> = Size2D::new(101, 103);
    const TIME: i32 = 100;
    
    fn part1(input: String) {
        let robots = parse(&input);
        let new_pos: Vec<Point2D<i32>> = robots.iter()
            .map(|&(p, v)| (p + v * TIME).rem_euclid(&ROOM))
            .collect();
    
        assert_eq!(ROOM.width % 2, 1);
        assert_eq!(ROOM.height % 2, 1);
        let mid_x = ROOM.width / 2;
        let mid_y = ROOM.height / 2;
        
        let mut q = [0u32; 4];
        for p in new_pos {
            use std::cmp::Ordering::*;
            match (p.x.cmp(&mid_x), p.y.cmp(&mid_y)) {
                (Less, Less) => q[0] += 1,
                (Greater, Less) => q[1] += 1,
                (Less, Greater) => q[2] += 1,
                (Greater, Greater) => q[3] += 1,
                _ => {}
            };
        }
        let prod = q[0] * q[1] * q[2] * q[3];
        println!("{prod}");
    }
    
    fn print_map(map: &[Vec<bool>]) {
        for row in map {
            for p in row {
                if *p { print!("#") } else { print!(".") }
            }
            println!();
        }
        println!();
    }
    
    
    fn part2(input: String) {
        let mut robots = parse(&input);
        let mut map = vec![vec![false; ROOM.width as usize]; ROOM.height as usize];
        for i in 1.. {
            let mut overlap = false;
            for (p, v) in &mut robots {
                *p = (*p + *v).rem_euclid(&ROOM);
                if map[p.y as usize][p.x as usize] {
                    // Found two robots on the same spot,
                    // which is used as a heuristic for detecting the easter egg.
                    overlap = true;
                } else {
                    map[p.y as usize][p.x as usize] = true;
                }
            }
            if !overlap {
                print_map(&map);
                println!("Round: {i}");
                break;
            }
            for row in &mut map {
                row.fill(false);
            }
        }
    }
    
    util::aoc_main!();
    

    Also on github