Working
This commit is contained in:
parent
18ee41a59a
commit
c025aee62a
@ -3,22 +3,74 @@ use anyhow::{Result, bail};
|
|||||||
|
|
||||||
mod parse;
|
mod parse;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct MapRange {
|
||||||
|
base: usize,
|
||||||
|
target: usize,
|
||||||
|
}
|
||||||
|
|
||||||
/// Stores a map as a series of contiguous offset ranges.
|
/// Stores a map as a series of contiguous offset ranges.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Map {
|
struct Map {
|
||||||
from: String,
|
from: String,
|
||||||
to: String,
|
to: String,
|
||||||
ranges: Vec<(Range<usize>, Range<usize>)>,
|
ranges: Vec<MapRange>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Map {
|
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 {
|
fn lookup(&self, src: usize) -> usize {
|
||||||
todo!()
|
let range = &self.ranges[self.range_idx(src)];
|
||||||
|
(src + range.target) - range.base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -32,17 +32,16 @@ fn map<R: BufRead>(s: &mut Lines<R>) -> Option<Result<Map>> {
|
|||||||
loop {
|
loop {
|
||||||
let line = s.next().ok_or(anyhow!("Unterminated map"))??;
|
let line = s.next().ok_or(anyhow!("Unterminated map"))??;
|
||||||
if line.is_empty() { break }
|
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<R: BufRead>(s: R) -> Result<( Vec<usize>, Vec<Map>)> {
|
pub fn input<R: BufRead>(s: R) -> Result<(Vec<usize>, Vec<Map>)> {
|
||||||
let mut s = s.lines();
|
let mut s = s.lines();
|
||||||
|
|
||||||
let seeds = seeds(&s.next().ok_or(anyhow!("EOF"))??)?;
|
let seeds = seeds(&s.next().ok_or(anyhow!("EOF"))??)?;
|
||||||
@ -50,7 +49,7 @@ pub fn input<R: BufRead>(s: R) -> Result<( Vec<usize>, Vec<Map>)> {
|
|||||||
bail!("Missing empty line after seeds")
|
bail!("Missing empty line after seeds")
|
||||||
}
|
}
|
||||||
|
|
||||||
let maps = unfold(s, map).collect::<Result<_>>()?;
|
let maps = unfold(s, map).collect::<Result<Vec<_>>>()?;
|
||||||
|
|
||||||
Ok((seeds, maps))
|
Ok((seeds, maps))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user