Skip to content
Snippets Groups Projects

AoC 2023 day 13

  • Clone with SSH
  • Clone with HTTPS
  • Embed
  • Share
    The snippet can be accessed without any authentication.
    Authored by s91149
    Edited
    main.rs 3.84 KiB
    fn main() {
        let input = std::fs::read_to_string("../inputs/input.txt").unwrap();
    
        let blocks: Vec<Block> = input
            .split("\n\n")
            .map(|block| {
                let block: Vec<Vec<char>> = block
                    .lines()
                    .map(|line| line.chars().collect::<Vec<char>>())
                    .collect();
                Block(block)
            })
            .collect();
    
        part_1(&blocks);
        part_2(&blocks);
    }
    
    #[derive(Clone)]
    struct Block(Vec<Vec<char>>);
    
    impl Block {
        fn transpose(&self) -> Self {
            let block = &self.0;
            let mut transposed: Vec<Vec<char>> = Vec::new();
            let block_height = block.len();
            let block_width = block[1].len();
    
            for x in 0..block_width {
                let mut v = Vec::with_capacity(block_height);
                for y in 0..block_height {
                    v.push(block[y][x]);
                }
                transposed.push(v);
            }
            Block(transposed)
        }
    
        fn count_above_reflect_point(&self) -> u32 {
            let block = &self.0;
            for i in 1..block.len() {
                if block[i] == block[i - 1] {
                    let before = &block[..i];
                    let after = &block[i..];
                    if before.iter().rev().zip(after.iter()).all(|(a, b)| a == b) {
                        return i as u32;
                    }
                }
            }
            0
        }
    
        fn find_all_reflection_points(&self) -> Vec<u32> {
            let block = &self.0;
    
            let mut v = Vec::new();
            for i in 1..block.len() {
                if block[i] == block[i - 1] {
                    let before = &block[..i];
                    let after = &block[i..];
                    if before.iter().rev().zip(after.iter()).all(|(a, b)| a == b) {
                        v.push(i as u32);
                    }
                }
            }
            v
        }
    }
    
    fn part_1(blocks: &[Block]) {
        let mut above_sum = 0;
        let mut left_sum = 0;
        for block in blocks.iter() {
            above_sum += block.count_above_reflect_point();
            let transposed = block.transpose();
            left_sum += transposed.count_above_reflect_point();
        }
    
        println!("part 1: {}", left_sum + 100 * above_sum);
    }
    
    fn part_2(blocks: &[Block]) {
        let mut above_sum = 0;
        let mut left_sum = 0;
    
        'outer: for block in blocks.iter() {
            let block_height = block.0.len();
            let block_width = block.0[0].len();
    
            let n_above = block.find_all_reflection_points();
            let transposed = block.transpose();
            let n_left = transposed.find_all_reflection_points();
    
            for y in 0..block_height {
                for x in 0..block_width {
                    let mut modified_block: Block = block.clone();
    
                    modified_block.0[y][x] = match modified_block.0[y][x] {
                        '#' => '.',
                        '.' => '#',
                        _ => unreachable!(),
                    };
    
                    let modified_n_above = modified_block.find_all_reflection_points();
                    let transposed_modified_block = modified_block.transpose();
                    let modified_n_left = transposed_modified_block.find_all_reflection_points();
    
                    if !modified_n_above.is_empty() && modified_n_above != n_above {
                        let new_res = modified_n_above
                            .iter()
                            .find(|&item| !n_above.contains(item))
                            .unwrap();
                        above_sum += new_res;
                        continue 'outer;
                    }
    
                    if !modified_n_left.is_empty() && modified_n_left != n_left {
                        let new_res = modified_n_left
                            .iter()
                            .find(|&item| !n_left.contains(item))
                            .unwrap();
                        left_sum += new_res;
                        continue 'outer;
                    }
                }
            }
        }
    
        println!("part 2: {}", left_sum + 100 * above_sum);
    }
    0% Loading or .
    You are about to add 0 people to the discussion. Proceed with caution.
    Finish editing this message first!
    Please register or to comment