diff --git a/2023/rust/src/day5.rs b/2023/rust/src/day5.rs new file mode 100644 index 0000000..734c534 --- /dev/null +++ b/2023/rust/src/day5.rs @@ -0,0 +1,156 @@ +mod prelude; +use std::collections::HashMap; +extern crate nom; +use nom::{ + branch::alt, + bytes::complete::{tag, take_while}, + character::complete::{line_ending, newline, space1}, + combinator::{map_res, value}, + multi::separated_list0, + sequence::tuple, + IResult, +}; + +use crate::prelude::*; + +fn main() { + Day5::show(day_input(5), day_input(5)) +} + +#[derive(Hash, Debug, PartialEq, Eq, Clone)] +enum Layer { + Seed, + Soil, + Fertilizer, + Water, + Light, + Temperature, + Humidity, + Location, +} + +#[derive(Hash, Eq, Debug, PartialEq, Clone)] +struct LayerDir { + from: Layer, + to: Layer, +} + +#[derive(Debug)] +struct Mapping { + from_start: usize, + to_start: usize, + length: usize, +} + +#[derive(Debug)] +struct Almanac { + seeds: Vec, + mappings: HashMap>, +} + +fn layer(input: &str) -> IResult<&str, Layer> { + alt(( + value(Layer::Seed, tag("seed")), + value(Layer::Soil, tag("soil")), + value(Layer::Fertilizer, tag("fertilizer")), + value(Layer::Water, tag("water")), + value(Layer::Light, tag("light")), + value(Layer::Temperature, tag("temperature")), + value(Layer::Humidity, tag("humidity")), + value(Layer::Location, tag("location")), + ))(input) +} + +fn int(input: &str) -> IResult<&str, usize> { + map_res(take_while(char::is_numeric), str::parse)(input) +} + +fn mapping(input: &str) -> IResult<&str, Mapping> { + println!("mapping input: {input:?}"); + let (input, nums) = separated_list0(space1, int)(input)?; + println!("nums: {nums:?}"); + Ok(( + input, + Mapping { + from_start: nums[0], + to_start: nums[1], + length: nums[2], + }, + )) +} + +fn mapping_entry(input: &str) -> IResult<&str, (LayerDir, Vec)> { + // TODO: this is probably confusing my parser since the newline separator would need to lookahead? + let (input, (from, _, to, _)) = tuple((layer, tag("-to-"), layer, tag(" map:\n")))(input)?; + // take while here + let (input, mappings) = separated_list0(newline, mapping)(input)?; + Ok((input, (LayerDir { from, to }, mappings))) +} + +fn almanac(input: &str) -> IResult<&str, Almanac> { + let (input, seeds) = separated_list0(space1, int)(tag("seeds: ")(input)?.0)?; + let (input, mapping_tuples) = + separated_list0(tuple((line_ending, line_ending)), mapping_entry)(tag("\n\n")(input)?.0)?; + let mappings: HashMap> = mapping_tuples.into_iter().collect(); + Ok((input, Almanac { seeds, mappings })) +} + +struct Day5 {} +impl AoCSolution for Day5 { + type Input = String; + type Solution = usize; + + fn part1(input: Self::Input) -> Self::Solution { + let almanac = almanac(&input); + println!("{almanac:?}"); + 0 + } + + fn part2(input: Self::Input) -> Self::Solution { + 0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let input = r#"seeds: 79 14 55 13 + +seed-to-soil map: +50 98 2 +52 50 48 + +soil-to-fertilizer map: +0 15 37 +37 52 2 +39 0 15 + +fertilizer-to-water map: +49 53 8 +0 11 42 +42 0 7 +57 7 4 + +water-to-light map: +88 18 7 +18 25 70 + +light-to-temperature map: +45 77 23 +81 45 19 +68 64 13 + +temperature-to-humidity map: +0 69 1 +1 0 69 + +humidity-to-location map: +60 56 37 +56 93 4"#; + assert_eq!(Day5::part1(input.into()), 35); + assert_eq!(Day5::part2(input.into()), 0); + } +} diff --git a/2023/rust/src/template.rs b/2023/rust/src/template.rs new file mode 100644 index 0000000..f6d6739 --- /dev/null +++ b/2023/rust/src/template.rs @@ -0,0 +1,32 @@ +mod prelude; +use crate::prelude::*; + +fn main() { + Day5::show(day_input(5), day_input(5)) +} + +struct Day5 {} +impl AoCSolution for Day5 { + type Input = String; + type Solution = usize; + + fn part1(input: Self::Input) -> Self::Solution { + 0 + } + + fn part2(input: Self::Input) -> Self::Solution { + 0 + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let input = r#""#; + assert_eq!(Day2::part1(input.into()), 1); + assert_eq!(Day2::part2(input.into()), 0); + } +}