diff --git a/2022/day04-camp_cleanup/src/lib.rs b/2022/day04-camp_cleanup/src/lib.rs new file mode 100644 index 0000000..0cc8eeb --- /dev/null +++ b/2022/day04-camp_cleanup/src/lib.rs @@ -0,0 +1,67 @@ +use core::fmt::Display; + +#[derive(Debug, PartialEq, Eq)] +pub enum ParseError { + LineMalformed(String), +} + +impl Display for ParseError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::LineMalformed(v) => write!(f, "Line is malformed: {v}"), + } + } +} + +fn fully_contained(pair: &str) -> Result { + let ((l1, r1), (l2, r2)) = parse_into_tuples(pair)?; + Ok(l1<=l2 && r1>=r2 || l2<=l1 && r2>=r1) +} + +fn overlapping(pair: &str) -> Result { + let ((l1, r1), (l2, r2)) = parse_into_tuples(pair)?; + Ok(l1<=l2 && r1>=l2 || l2<=l1 && r2>=l1) +} + +fn parse_into_tuples(pair: &str) -> Result<((u32, u32), (u32, u32)), ParseError> { + if let Some((first, second)) = pair.split_once(',') { + if let Some ((l1, r1)) = first.split_once('-') { + if let Some((l2, r2)) = second.split_once('-') { + let l1 = l1.parse::().expect("Malformed ID: Not a number"); + let l2 = l2.parse::().expect("Malformed ID: Not a number"); + let r1 = r1.parse::().expect("Malformed ID: Not a number"); + let r2 = r2.parse::().expect("Malformed ID: Not a number"); + return Ok(((l1, r1), (l2, r2))); + } + } + } + Err(ParseError::LineMalformed(pair.to_string())) +} + +pub fn run(input: &str) -> Result<(usize, usize), ParseError> { + let first = input.lines().map(fully_contained).collect::, _>>()?.iter().filter(|l| **l).count(); + let second = input.lines().map(overlapping).collect::, _>>()?.iter().filter(|l| **l).count(); + Ok((first, second)) +} + +#[cfg(test)] +mod tests { + use super::*; + use std::fs::read_to_string; + + fn read_file(name: &str) -> String { + read_to_string(name).expect(&format!("Unable to read file: {name}")[..]).trim().to_string() + } + + #[test] + fn test_sample() { + let sample_input = read_file("tests/sample_input"); + assert_eq!(run(&sample_input), Ok((2, 4))); + } + + #[test] + fn test_challenge() { + let challenge_input = read_file("tests/challenge_input"); + assert_eq!(run(&challenge_input), Ok((560, 839))); + } +} diff --git a/2022/day04-camp_cleanup/src/main.rs b/2022/day04-camp_cleanup/src/main.rs deleted file mode 100644 index cba4bff..0000000 --- a/2022/day04-camp_cleanup/src/main.rs +++ /dev/null @@ -1,61 +0,0 @@ -use std::fs; - -fn read_file(path: &str) -> String { - fs::read_to_string(path) - .expect("File not Found") -} - -fn fully_contained(pair: &str) -> bool { - let ((l1, r1), (l2, r2)) = parse_into_tuples(pair); - l1<=l2 && r1>=r2 || l2<=l1 && r2>=r1 -} - -fn overlapping(pair: &str) -> bool { - let ((l1, r1), (l2, r2)) = parse_into_tuples(pair); - l1<=l2 && r1>=l2 || l2<=l1 && r2>=l1 -} - -fn parse_into_tuples(pair: &str) -> ((u32, u32), (u32, u32)) { - if let Some((first, second)) = pair.split_once(',') { - if let Some ((l1, r1)) = first.split_once('-') { - if let Some((l2, r2)) = second.split_once('-') { - let l1 = l1.parse::().expect("Malformed ID: Not a number"); - let l2 = l2.parse::().expect("Malformed ID: Not a number"); - let r1 = r1.parse::().expect("Malformed ID: Not a number"); - let r2 = r2.parse::().expect("Malformed ID: Not a number"); - return ((l1, r1), (l2, r2)); - } - } - } - panic!("Malformatted input"); -} - -fn main() { - //let contents = read_file("sample_input"); - let contents = read_file("input"); - - let fully_contained_count = contents.lines() - .filter(|l| fully_contained(l)) - .count(); - - let overlapping_count = contents.lines() - .filter(|l| overlapping(l)) - .count(); - - println!("For {fully_contained_count} pairs, one is fully contained within the other."); - println!("{overlapping_count} pairs have at least some overlap.") -} - -#[test] -fn sample_input() { - let contents = read_file("tests/sample_input"); - assert_eq!(contents.lines().filter(|l| fully_contained(l)).count(), 2); - assert_eq!(contents.lines().filter(|l| overlapping(l)).count(), 4); -} - -#[test] -fn challenge_input() { - let contents = read_file("tests/input"); - assert_eq!(contents.lines().filter(|l| fully_contained(l)).count(), 560); - assert_eq!(contents.lines().filter(|l| overlapping(l)).count(), 839); -} diff --git a/2022/day04-camp_cleanup/tests/input b/2022/day04-camp_cleanup/tests/challenge_input similarity index 100% rename from 2022/day04-camp_cleanup/tests/input rename to 2022/day04-camp_cleanup/tests/challenge_input