diff --git a/src/five.rs b/src/five.rs index 743f62d..da5a0d8 100644 --- a/src/five.rs +++ b/src/five.rs @@ -1,17 +1,107 @@ +use regex::Regex; + use crate::common::load_input; -struct TranslationRange{ - source_start: u32, - destination_start: u32, - range: u32, +#[derive(Debug)] +struct TranslationRange { + source_start: u64, + destination_start: u64, + range: u64, } +#[derive(Debug)] struct TranslationMap { - ranges: Vec + ranges: Vec, +} + +impl TranslationRange { + fn in_range(&self, num: u64) -> bool { + return (num >= self.source_start) && (num < (self.source_start + self.range)); + } + + fn translate(&self, num: u64) -> u64 { + return (num - self.source_start) + self.destination_start; + } +} + +impl TranslationMap { + fn translate(&self, num: u64) -> u64 { + let t: Vec<&TranslationRange> = self.ranges.iter().filter(|e| e.in_range(num)).collect(); + + if t.len() > 1 { + panic!("Fucked up"); + } + + if t.len() == 1 { + return t.get(0).unwrap().translate(num); + } + + return num; + } +} + +fn parse_input(lines: &[String]) -> Vec { + let mut translation_map: Vec = vec![]; + + let regex = Regex::new(r"(?m)(\d+) (\d+) (\d+)").unwrap(); + + for line in lines.iter() { + if line.is_empty() { + continue; + } + + if line.contains("map") { + translation_map.push(TranslationMap { ranges: vec![] }); + continue; + } + + let result = regex.captures(line).unwrap(); + let dest: u64 = result.get(1).unwrap().as_str().parse().unwrap(); + let source: u64 = result.get(2).unwrap().as_str().parse().unwrap(); + let range: u64 = result.get(3).unwrap().as_str().parse().unwrap(); + + translation_map + .last_mut() + .unwrap() + .ranges + .push(TranslationRange { + source_start: source, + destination_start: dest, + range: range, + }) + } + + return translation_map; +} + +fn get_seeds(line: &str) -> Vec { + let regex = Regex::new(r"(?m)(\d+)").unwrap(); + let result = regex.captures_iter(line); + + return result + .map(|e| e.get(0).unwrap().as_str().parse::().unwrap()) + .collect(); +} + +fn seed_to_location(maps: &Vec, num: u64) -> u64 { + let mut result = num; + for map in maps.iter() { + result = map.translate(result); + } + + return result; } pub fn run() -> Result> { let lines = load_input("./input/5.txt")?; + let seeds = get_seeds(lines.get(0).unwrap().as_str()); + let maps = parse_input(&lines[1..]); - Ok(999) -} \ No newline at end of file + let min = seeds + .iter() + .map(|e| seed_to_location(&maps, *e)) + .min() + .unwrap(); + + Ok(min.try_into().unwrap()) +}