diff --git a/2022/Cargo.toml b/2022/Cargo.toml index da1fc22..60f9732 100644 --- a/2022/Cargo.toml +++ b/2022/Cargo.toml @@ -19,6 +19,10 @@ path = "src/day2.rs" name = "day3" path = "src/day3.rs" +[[bin]] +name = "day4" +path = "src/day4.rs" + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/2022/src/day4.rs b/2022/src/day4.rs new file mode 100644 index 0000000..344b15d --- /dev/null +++ b/2022/src/day4.rs @@ -0,0 +1,89 @@ +const DATA: &'static str = include_str!("../data/day4.txt"); +// const DATA: &'static str = " +// 2-4,6-8 +// 2-3,4-5 +// 5-7,7-9 +// 2-8,3-7 +// 6-6,4-6 +// 2-6,4-8 +// "; + + +#[derive(Debug)] +enum DataError { + NotANumber, + NotAPair, + NotARange, +} + + +struct Range { + start: u32, + end: u32, +} + +impl Range { + fn contains(&self, other: &Range) -> bool { + self.start <= other.start && self.end >= other.end + } + + fn overlaps(&self, other: &Range) -> bool { + // what if self.start == other.start or self.end == other.end? + if self.start <= other.start && self.end >= other.start { + return true; + } + + if self.start <= other.end && self.end >= other.end { + return true; + } + false + } +} + +impl std::str::FromStr for Range { + type Err = DataError; + + fn from_str(s: &str) -> Result { + let mut bounds = s.split('-'); + + let start = bounds.next() + .ok_or(DataError::NotARange)? + .parse::() + .map_err(|_e| DataError::NotANumber)?; + let end = bounds.next() + .ok_or(DataError::NotARange)? + .parse::() + .map_err(|_e| DataError::NotANumber)?; + + Ok(Range {start, end}) + } +} + + +fn main() -> Result<(), DataError> { + let ranges = DATA.trim() + .lines() + .map(|line| { + let mut pairs = line.split(','); + let left: Range = pairs.next() + .ok_or(DataError::NotAPair)? + .parse()?; + let right: Range = pairs.next() + .ok_or(DataError::NotAPair)? + .parse()?; + Ok((left, right)) + }) + .collect::, DataError>>()?; + + let total_supersets = ranges.iter() + .filter(|(a, b)| a.contains(b) || b.contains(a)) + .count(); + println!("Part 1: {total_supersets}"); + + let total_overlaps = ranges.iter() + .filter(|(a, b)| a.overlaps(b) || b.contains(a) || a.contains(b)) + .count(); + println!("Part 2: {total_overlaps}"); + + Ok(()) +}