Day 2: Red-Nosed Reports

Megathread guidelines

  • Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
  • You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://blocks.programming.dev/ if you prefer sending it through a URL

FAQ

  • Deebster@programming.dev
    link
    fedilink
    arrow-up
    2
    ·
    edit-2
    23 days ago

    I forgot that this started yesterday, so I’m already behind. I quite like my solution for part one, but part two will have to wait edit: part 2 was a lot simpler than I thought after a night’s sleep.

    Rust

    use color_eyre::eyre;
    use std::{fs, num, str::FromStr};
    
    #[derive(Debug, PartialEq, Eq)]
    struct Report(Vec<isize>);
    
    impl FromStr for Report {
        type Err = num::ParseIntError;
    
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            let v: Result<Vec<isize>, _> = s
                .split_whitespace()
                .map(|num| num.parse::<isize>())
                .collect();
            Ok(Report(v?))
        }
    }
    
    impl Report {
        fn is_safe(&self) -> bool {
            let ascending = self.0[1] > self.0[0];
            let (low, high) = if ascending { (1, 3) } else { (-3, -1) };
            self.0.windows(2).all(|w| {
                let a = w[0];
                let b = w[1];
                b >= a + low && b <= a + high
            })
        }
    
        fn is_dampsafe(&self) -> bool {
            if self.is_safe() {
                return true;
            }
            for i in 0..self.0.len() {
                let damped = {
                    let mut v = self.0.clone();
                    v.remove(i);
                    Self(v)
                };
                if damped.is_safe() {
                    return true;
                }
            }
            false
        }
    }
    
    fn main() -> eyre::Result<()> {
        color_eyre::install()?;
    
        let part1 = part1("d02/input.txt")?;
        let part2 = part2("d02/input.txt")?;
        println!("Part 1: {part1}\nPart 2: {part2}");
        Ok(())
    }
    
    fn part1(filepath: &str) -> eyre::Result<isize> {
        let mut num_safe = 0;
        for l in fs::read_to_string(filepath)?.lines() {
            if Report::from_str(l)?.is_safe() {
                num_safe += 1;
            }
        }
        Ok(num_safe)
    }
    
    fn part2(filepath: &str) -> eyre::Result<isize> {
        let mut num_safe = 0;
        for l in fs::read_to_string(filepath)?.lines() {
            if Report::from_str(l)?.is_dampsafe() {
                num_safe += 1;
            }
        }
        Ok(num_safe)
    }
    
    Tests
    #[cfg(test)]
    mod tests {
        use super::*;
    
        #[test]
        fn sample_part1() {
            assert_eq!(part1("test.txt").unwrap(), 2);
        }
    
        #[test]
        fn sample_part2() {
            assert_eq!(part2("test.txt").unwrap(), 4);
        }
    }