diff --git a/2023/day5/example-input.txt b/2023/day5/src/example-input.txt similarity index 100% rename from 2023/day5/example-input.txt rename to 2023/day5/src/example-input.txt diff --git a/2023/day5/input.txt b/2023/day5/src/input.txt similarity index 100% rename from 2023/day5/input.txt rename to 2023/day5/src/input.txt diff --git a/2023/day5/src/main.rs b/2023/day5/src/main.rs index 43148d4..e14ff27 100644 --- a/2023/day5/src/main.rs +++ b/2023/day5/src/main.rs @@ -1,10 +1,13 @@ +use std::collections::{HashMap, VecDeque}; use std::ops::Range; -use std::collections::HashMap; -const FILE_STR: &'static str = include_str!("input.txt"); +use crate::DataType::Soil; -#[derive(Debug)] +const FILE_STR: &'static str = include_str!("input.txt"); +const EXAMPLE_FILE_STR: &'static str = include_str!("example-input.txt"); + +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] enum DataType { - Seeds, + Seed, Soil, Fertilizer, Water, @@ -14,6 +17,22 @@ enum DataType { Location, } +impl DataType { + fn try_from(s: &str) -> Option { + match s { + "seed" => Some(Self::Seed), + "soil" => Some(Self::Soil), + "fertilizer" => Some(Self::Fertilizer), + "water" => Some(Self::Water), + "light" => Some(Self::Light), + "temperature" => Some(Self::Temperature), + "humidity" => Some(Self::Humidity), + "location" => Some(Self::Location), + _ => None, + } + } +} + #[derive(Debug, Default)] struct DataMap { from_range: Range, @@ -27,7 +46,7 @@ impl DataMap { DataMap { from_range, - to_range + to_range, } } @@ -41,7 +60,7 @@ impl DataMap { match dest_index { Some(n) => n, - None => src_value + None => src_value, } } @@ -55,28 +74,85 @@ impl DataMap { match src_index { Some(n) => n, - None => dest_value + None => dest_value, } } } +type MapMap = HashMap<(DataType, DataType), Vec>; + #[derive(Debug, Default)] struct Almanac { seeds: Vec, - maps: HashMap<(DataType, DataType), Vec>, + maps: MapMap, } impl Almanac { fn parse(input: &str) -> Self { + let mut data_chunks: VecDeque<_> = input.split("\n\n").collect(); + let seeds: Vec = data_chunks + .pop_front() + .unwrap() + .split(':') + .collect::>() + .pop() + .unwrap() + .split_whitespace() + .map(|s| s.trim()) + .map(|s| s.parse::().unwrap()) + .collect(); + + let maps = data_chunks + .into_iter() + .map(|chunk| { + let mut lines: VecDeque<_> = chunk.split("\n").collect(); + let type_line_parts: Vec<_> = + lines.pop_front().unwrap().split_whitespace().collect(); + let types: Vec<_> = type_line_parts[0] + .split("-to-") + .map(|s| DataType::try_from(s.trim()).unwrap()) + .collect(); + let (from, to) = (types[0], types[1]); + let mappings: Vec = lines + .into_iter() + .map(|line| { + line.split_whitespace() + .map(|s| s.trim()) + .filter(|s| s.len() > 0) + .map(|s| s.parse::().unwrap()) + .collect::>() + }) + .map(|m| DataMap::new(m[0], m[1], m[2])) + .collect(); + + ((from, to), mappings) + }) + .collect(); + + Almanac { seeds, maps } + } + + fn x_from_y(&self, x: DataType, y: DataType, search: u64) -> u64 { + let maps = self.maps.get(&(y, x)).expect(&format!("Missing mapping from {:?} to {:?}", x, y)); todo!(); } + + fn soil_from_seed(&self, seed: u64) -> u64 { + use DataType::*; + + self.x_from_y(Soil, Seed, seed) + } } fn main() { - println!("Hello, world!"); + let almanac = Almanac::parse(EXAMPLE_FILE_STR); + let soil = almanac.soil_from_seed(79); } #[cfg(test)] mod tests { const EXAMPLE_FILE_STR: &'static str = include_str!("example-input.txt"); -} \ No newline at end of file + + #[test] + fn test_parse() {} +}