diff --git a/day5/src/main.rs b/day5/src/main.rs index 5465202..3322450 100644 --- a/day5/src/main.rs +++ b/day5/src/main.rs @@ -3,22 +3,74 @@ use anyhow::{Result, bail}; mod parse; +#[derive(Debug)] +struct MapRange { + base: usize, + target: usize, +} + /// Stores a map as a series of contiguous offset ranges. #[derive(Debug)] struct Map { from: String, to: String, - ranges: Vec<(Range, Range)>, + ranges: Vec, } impl Map { + fn from_ranges(from: String, to: String, mut v: Vec<(usize,usize,usize)>) -> Self { + v.sort_by_key(|r| r.1); + + let mut ranges = Vec::with_capacity(2*v.len() + 1); + ranges.push(MapRange {base: 0, target: 0 } ); + + for (target, base, len) in v { + if ranges.last().unwrap().base == base { + ranges.pop(); + } + ranges.push(MapRange { base, target }); + ranges.push(MapRange { base: base+len, target: base+len }); + } + + Self { from, to, ranges } + } + + fn range_idx(&self, target: usize) -> usize { + self.ranges.binary_search_by_key(&target, |r| r.base) + .unwrap_or_else(|i| i-1) + } + fn lookup(&self, src: usize) -> usize { - todo!() + let range = &self.ranges[self.range_idx(src)]; + (src + range.target) - range.base } } fn main() -> Result<()> { + let (seeds, maps) = parse::input(stdin().lock())?; + + eprintln!("{seeds:?}, {maps:?}"); + + let mut current= "seed"; + + for map in &maps { + if map.from != current { bail!("Wrong map order, expected {current}") } + current = &map.to; + } + + let best = seeds.iter() + .map(|&s| { + let mut cur = s; + eprint!("{cur}"); + for m in &maps { + cur = m.lookup(cur); + eprint!(" -> {cur}") + } + eprintln!(); + cur + }).min(); + println!("lowest location: {best:?}"); Ok(()) } diff --git a/day5/src/parse.rs b/day5/src/parse.rs index 80e13ab..8873618 100644 --- a/day5/src/parse.rs +++ b/day5/src/parse.rs @@ -32,17 +32,16 @@ fn map(s: &mut Lines) -> Option> { loop { let line = s.next().ok_or(anyhow!("Unterminated map"))??; if line.is_empty() { break } - let (dst, src, len) = range(&line)?; + ranges.push(range(&line)?); - ranges.push((src..src+len, dst..dst+len)); } - Ok(Map { from: from.to_owned(), to: to.to_owned(), ranges }) + Ok(Map::from_ranges(from.to_owned(), to.to_owned(), ranges)) })()) } -pub fn input(s: R) -> Result<( Vec, Vec)> { +pub fn input(s: R) -> Result<(Vec, Vec)> { let mut s = s.lines(); let seeds = seeds(&s.next().ok_or(anyhow!("EOF"))??)?; @@ -50,7 +49,7 @@ pub fn input(s: R) -> Result<( Vec, Vec)> { bail!("Missing empty line after seeds") } - let maps = unfold(s, map).collect::>()?; + let maps = unfold(s, map).collect::>>()?; Ok((seeds, maps)) }