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,12 +32,11 @@ 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))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    })())
 | 
					    })())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user