generated from janezicmatej/aoc-template
	solution: day 5 clean
This commit is contained in:
		@@ -1,7 +1,12 @@
 | 
				
			|||||||
use std::{cmp::min, str::FromStr};
 | 
					use std::{
 | 
				
			||||||
 | 
					    cmp::{max, min},
 | 
				
			||||||
 | 
					    str::FromStr,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use aoc::parsers::to_vec;
 | 
					use aoc::parsers::to_vec;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PairRange = (u64, u64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
struct Mapping {
 | 
					struct Mapping {
 | 
				
			||||||
    destination: u64,
 | 
					    destination: u64,
 | 
				
			||||||
@@ -29,45 +34,37 @@ impl Mapping {
 | 
				
			|||||||
        n >= self.source && n < self.source + self.range
 | 
					        n >= self.source && n < self.source + self.range
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn contains_any(&self, s: u64, r: u64) -> bool {
 | 
					    fn contains_any(&self, (s, r): PairRange) -> bool {
 | 
				
			||||||
        s < self.source + self.range && s + r > self.source
 | 
					        s < self.source + self.range && s + r > self.source
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn map(&self, n: u64) -> u64 {
 | 
					    fn map(&self, n: u64) -> u64 {
 | 
				
			||||||
        debug_assert!(self.contains(n));
 | 
					 | 
				
			||||||
        let shift = n - self.source;
 | 
					        let shift = n - self.source;
 | 
				
			||||||
        self.destination + shift
 | 
					        self.destination + shift
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn map_range(&self, s: u64, r: u64) -> ((u64, u64), Vec<(u64, u64)>) {
 | 
					    fn split_range(&self, (s, r): PairRange) -> [Option<PairRange>; 3] {
 | 
				
			||||||
        debug_assert!(self.contains_any(s, r));
 | 
					        let mut fences = [
 | 
				
			||||||
        let shift = {
 | 
					            s,
 | 
				
			||||||
            if self.contains(s) {
 | 
					            s + r,
 | 
				
			||||||
                s - self.source
 | 
					            max(self.source, s),
 | 
				
			||||||
 | 
					            min(self.source + self.range, s + r),
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					        fences.sort();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let mut v = Vec::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for i in 0..3 {
 | 
				
			||||||
 | 
					            let f = fences[i];
 | 
				
			||||||
 | 
					            let nf = fences[i + 1];
 | 
				
			||||||
 | 
					            if f != nf {
 | 
				
			||||||
 | 
					                v.push(Some((f, nf - f)))
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                0
 | 
					                v.push(None)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        let neg_shift = {
 | 
					 | 
				
			||||||
            if self.contains(s) {
 | 
					 | 
				
			||||||
                0
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                self.source - s
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        let dest_start = self.destination + shift;
 | 
					 | 
				
			||||||
        let dest_range = min(r - neg_shift, self.range - shift);
 | 
					 | 
				
			||||||
        let mut rest = Vec::new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if !self.contains(s) {
 | 
					 | 
				
			||||||
            rest.push((s, self.source - s));
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if r - neg_shift > dest_range {
 | 
					        v[..3].try_into().unwrap()
 | 
				
			||||||
            rest.push((self.source + self.range, r - dest_range))
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ((dest_start, dest_range), rest)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -125,10 +122,14 @@ pub fn part_two(input: &str) -> Option<u64> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        'queue: while let Some((s, r)) = seeds_ranges.pop() {
 | 
					        'queue: while let Some((s, r)) = seeds_ranges.pop() {
 | 
				
			||||||
            for map in mapping {
 | 
					            for map in mapping {
 | 
				
			||||||
                if map.contains_any(s, r) {
 | 
					                if map.contains_any((s, r)) {
 | 
				
			||||||
                    let (rng, rest) = map.map_range(s, r);
 | 
					                    let [pre, to_map, post] = map.split_range((s, r));
 | 
				
			||||||
                    new_ranges.push(rng);
 | 
					                    let to_map = to_map.unwrap();
 | 
				
			||||||
                    seeds_ranges.extend_from_slice(&rest);
 | 
					                    let mapped = (map.map(to_map.0), to_map.1);
 | 
				
			||||||
 | 
					                    new_ranges.push(mapped);
 | 
				
			||||||
 | 
					                    for r in [pre, post].into_iter().flatten() {
 | 
				
			||||||
 | 
					                        seeds_ranges.push(r);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    continue 'queue;
 | 
					                    continue 'queue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user