Skip to content
Snippets Groups Projects

AoC 2023 day 5

  • Clone with SSH
  • Clone with HTTPS
  • Embed
  • Share
    The snippet can be accessed without any authentication.
    Authored by s91149
    main.rs 3.24 KiB
    use std::ops::Range;
    
    fn main() {
        let input = std::fs::read_to_string("../inputs/input.txt").unwrap();
    
        let mut seeds: Vec<u64> = Vec::new();
        let mut all_ranges: Vec<Vec<Ranges>> = Vec::new();
    
        for block in input.split("\n\n") {
            if block.contains(": ") {
                seeds = block
                    .split(':')
                    .skip(1)
                    .map(|s| {
                        s.split_whitespace()
                            .map(|n| n.parse::<u64>().unwrap())
                            .collect::<Vec<u64>>()
                    })
                    .next()
                    .unwrap();
            } else {
                let numbers: String = block.split(":\n").skip(1).collect();
    
                let ranges_in_block: Vec<Ranges> = numbers
                    .lines()
                    .map(|number_line| {
                        let n: Vec<u64> = number_line
                            .split_whitespace()
                            .map(|n| n.parse().unwrap())
                            .collect();
    
                        if let &[dest_range_start, source_range_start, len] = &n[..] {
                            Ranges::new(dest_range_start, source_range_start, len)
                        } else {
                            unreachable!();
                        }
                    })
                    .collect();
                all_ranges.push(ranges_in_block);
            }
        }
    
        part_1(&seeds, &all_ranges);
        part_2(&seeds, &all_ranges);
    }
    
    fn part_1(seeds: &[u64], all_ranges: &[Vec<Ranges>]) {
        let location_numbers = seeds.iter().map(|seed| {
            let mut current_value = *seed;
            for block_of_ranges in all_ranges.iter() {
                if let Some(valid_range) = block_of_ranges
                    .iter()
                    .find(|ranges| ranges.source.contains(&current_value))
                {
                    let pos = current_value - valid_range.source.start;
                    current_value = valid_range.destination.start + pos;
                }
            }
            current_value
        });
    
        println!("part 1: {}", location_numbers.min().unwrap());
    }
    
    fn part_2(seeds: &[u64], all_ranges: &[Vec<Ranges>]) {
        let seed_ranges: Vec<Range<u64>> = seeds
            .chunks(2)
            .map(|c| {
                if let &[start, len] = c {
                    start..(start + len)
                } else {
                    unreachable!()
                }
            })
            .collect();
    
        for seed in 0..2402036949 {
            let mut current_value = seed;
            for block_of_ranges in all_ranges.iter().rev() {
                if let Some(valid_range) = block_of_ranges
                    .iter()
                    .find(|ranges| ranges.destination.contains(&current_value))
                {
                    let pos = current_value - valid_range.destination.start;
                    current_value = valid_range.source.start + pos;
                }
            }
            if seed_ranges.iter().any(|r| r.contains(&current_value)) {
                println!("part 2: {}", seed);
                return;
            };
        }
    }
    
    #[derive(Debug)]
    struct Ranges {
        source: Range<u64>,
        destination: Range<u64>,
    }
    
    impl Ranges {
        fn new(dest_range_start: u64, source_range_start: u64, len: u64) -> Self {
            Self {
                destination: dest_range_start..(dest_range_start + len),
                source: source_range_start..(source_range_start + len),
            }
        }
    }
    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