generated from janezicmatej/aoc-template
	solution: day5 ranges
Squashed commit of the following:
commit 000001603e10102f634c2f4ca7eb310ec72f1863
Author: Matej Janežič <janezic.mj@gmail.com>
Date:   Wed Dec 6 20:47:26 2023 +0100
    day(5): ranges
commit 0000015049
Author: Matej Janežič <janezic.mj@gmail.com>
Date:   Wed Dec 6 18:58:58 2023 +0100
    wip: solve with range type
			
			
This commit is contained in:
		@@ -1,17 +1,33 @@
 | 
				
			|||||||
use std::{
 | 
					use std::{
 | 
				
			||||||
    cmp::{max, min},
 | 
					    cmp::{max, min},
 | 
				
			||||||
 | 
					    fmt::Debug,
 | 
				
			||||||
 | 
					    ops::RangeInclusive,
 | 
				
			||||||
    str::FromStr,
 | 
					    str::FromStr,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use aoc::parsers::to_vec;
 | 
					use aoc::parsers::to_vec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type PairRange = (u64, u64);
 | 
					trait RangeInclusiveExt {
 | 
				
			||||||
 | 
					    fn overlaps(&self, other: &Self) -> bool;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl<T> RangeInclusiveExt for RangeInclusive<T>
 | 
				
			||||||
 | 
					where
 | 
				
			||||||
 | 
					    T: PartialOrd,
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    fn overlaps(&self, other: &Self) -> bool {
 | 
				
			||||||
 | 
					        self.contains(other.start()) || self.contains(other.end())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn build_range(start: u64, range: u64) -> RangeInclusive<u64> {
 | 
				
			||||||
 | 
					    start..=(start + range - 1)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
struct Mapping {
 | 
					struct Mapping {
 | 
				
			||||||
    destination: u64,
 | 
					    pub source: RangeInclusive<u64>,
 | 
				
			||||||
    source: u64,
 | 
					    pub destination: RangeInclusive<u64>,
 | 
				
			||||||
    range: u64,
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct ParseMappingError;
 | 
					struct ParseMappingError;
 | 
				
			||||||
@@ -22,49 +38,43 @@ impl FromStr for Mapping {
 | 
				
			|||||||
        let nums: Vec<u64> = to_vec(s, ' ');
 | 
					        let nums: Vec<u64> = to_vec(s, ' ');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Ok(Self {
 | 
					        Ok(Self {
 | 
				
			||||||
            destination: nums[0],
 | 
					            destination: build_range(nums[0], nums[2]),
 | 
				
			||||||
            source: nums[1],
 | 
					            source: build_range(nums[1], nums[2]),
 | 
				
			||||||
            range: nums[2],
 | 
					 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl Mapping {
 | 
					impl Mapping {
 | 
				
			||||||
    fn contains(&self, n: u64) -> bool {
 | 
					 | 
				
			||||||
        n >= self.source && n < self.source + self.range
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn contains_any(&self, (s, r): PairRange) -> bool {
 | 
					 | 
				
			||||||
        s < self.source + self.range && s + r > self.source
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fn map(&self, n: u64) -> u64 {
 | 
					    fn map(&self, n: u64) -> u64 {
 | 
				
			||||||
        let shift = n - self.source;
 | 
					        let shift = n - self.source.start();
 | 
				
			||||||
        self.destination + shift
 | 
					        self.destination.start() + shift
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn split_range(&self, (s, r): PairRange) -> [Option<PairRange>; 3] {
 | 
					    fn map_range(&self, r: RangeInclusive<u64>) -> RangeInclusive<u64> {
 | 
				
			||||||
 | 
					        self.map(*r.start())..=(self.map(*r.end()))
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn split_range(&self, r: RangeInclusive<u64>) -> [Option<RangeInclusive<u64>>; 3] {
 | 
				
			||||||
        let mut fences = [
 | 
					        let mut fences = [
 | 
				
			||||||
            s,
 | 
					            *r.start(),
 | 
				
			||||||
            s + r,
 | 
					            *r.end() + 1,
 | 
				
			||||||
            max(self.source, s),
 | 
					            max(*self.source.start(), *r.start()),
 | 
				
			||||||
            min(self.source + self.range, s + r),
 | 
					            min(*self.source.end() + 1, *r.end() + 1),
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fences.sort();
 | 
					        fences.sort();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut v = Vec::new();
 | 
					        const ARRAY_REPEAT_VALUE: Option<RangeInclusive<u64>> = None;
 | 
				
			||||||
 | 
					        let mut v = [ARRAY_REPEAT_VALUE; 3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for i in 0..3 {
 | 
					        for i in 0..3 {
 | 
				
			||||||
            let f = fences[i];
 | 
					            let f = fences[i];
 | 
				
			||||||
            let nf = fences[i + 1];
 | 
					            let nf = fences[i + 1];
 | 
				
			||||||
            if f != nf {
 | 
					            if f != nf {
 | 
				
			||||||
                v.push(Some((f, nf - f)))
 | 
					                v[i] = Some(f..=(nf - 1))
 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                v.push(None)
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        v
 | 
				
			||||||
        v[..3].try_into().unwrap()
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -95,7 +105,7 @@ pub fn part_one(input: &str) -> Option<u64> {
 | 
				
			|||||||
        let mut s = *seed;
 | 
					        let mut s = *seed;
 | 
				
			||||||
        'maps: for map in maps.iter() {
 | 
					        'maps: for map in maps.iter() {
 | 
				
			||||||
            for inner in map.iter() {
 | 
					            for inner in map.iter() {
 | 
				
			||||||
                if inner.contains(s) {
 | 
					                if inner.source.contains(&s) {
 | 
				
			||||||
                    s = inner.map(s);
 | 
					                    s = inner.map(s);
 | 
				
			||||||
                    continue 'maps;
 | 
					                    continue 'maps;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -111,22 +121,19 @@ pub fn part_one(input: &str) -> Option<u64> {
 | 
				
			|||||||
pub fn part_two(input: &str) -> Option<u64> {
 | 
					pub fn part_two(input: &str) -> Option<u64> {
 | 
				
			||||||
    let (first, rest) = input.split_once("\n\n").unwrap();
 | 
					    let (first, rest) = input.split_once("\n\n").unwrap();
 | 
				
			||||||
    let maps = parse_map(rest);
 | 
					    let maps = parse_map(rest);
 | 
				
			||||||
    let seeds = to_vec::<u64, _>(first.strip_prefix("seeds: ").unwrap(), ' ');
 | 
					    let mut seeds_ranges: Vec<_> = to_vec::<u64, _>(first.strip_prefix("seeds: ").unwrap(), ' ')
 | 
				
			||||||
    let mut seeds_ranges: Vec<_> = Vec::new();
 | 
					        .chunks(2)
 | 
				
			||||||
    for s in seeds.chunks(2) {
 | 
					        .map(|x| build_range(x[0], x[1]))
 | 
				
			||||||
        seeds_ranges.push((s[0], s[1]))
 | 
					        .collect();
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for mapping in maps.iter() {
 | 
					    for mapping in maps.iter() {
 | 
				
			||||||
        let mut new_ranges = Vec::new();
 | 
					        let mut new_ranges = Vec::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        'queue: while let Some((s, r)) = seeds_ranges.pop() {
 | 
					        'queue: while let Some(rng) = seeds_ranges.pop() {
 | 
				
			||||||
            for map in mapping {
 | 
					            for map in mapping {
 | 
				
			||||||
                if map.contains_any((s, r)) {
 | 
					                if map.source.overlaps(&rng) {
 | 
				
			||||||
                    let [pre, to_map, post] = map.split_range((s, r));
 | 
					                    let [pre, to_map, post] = map.split_range(rng);
 | 
				
			||||||
                    let to_map = to_map.unwrap();
 | 
					                    new_ranges.push(map.map_range(to_map.unwrap()));
 | 
				
			||||||
                    let mapped = (map.map(to_map.0), to_map.1);
 | 
					 | 
				
			||||||
                    new_ranges.push(mapped);
 | 
					 | 
				
			||||||
                    for r in [pre, post].into_iter().flatten() {
 | 
					                    for r in [pre, post].into_iter().flatten() {
 | 
				
			||||||
                        seeds_ranges.push(r);
 | 
					                        seeds_ranges.push(r);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@@ -134,13 +141,17 @@ pub fn part_two(input: &str) -> Option<u64> {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            new_ranges.push((s, r));
 | 
					            new_ranges.push(rng);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        seeds_ranges = new_ranges;
 | 
					        seeds_ranges = new_ranges;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    seeds_ranges.iter().map(|(x, _)| *x).min()
 | 
					    seeds_ranges
 | 
				
			||||||
 | 
					        .iter()
 | 
				
			||||||
 | 
					        .map(RangeInclusive::start)
 | 
				
			||||||
 | 
					        .min()
 | 
				
			||||||
 | 
					        .copied()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
aoc::solution!(5);
 | 
					aoc::solution!(5);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user