this post was submitted on 02 Dec 2024
44 points (97.8% liked)

Advent Of Code

996 readers
4 users here now

An unofficial home for the advent of code community on programming.dev!

Advent of Code is an annual Advent calendar of small programming puzzles for a variety of skill sets and skill levels that can be solved in any programming language you like.

AoC 2024

Solution Threads

M T W T F S S
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25

Rules/Guidelines

Relevant Communities

Relevant Links

Credits

Icon base by Lorc under CC BY 3.0 with modifications to add a gradient

console.log('Hello World')

founded 1 year ago
MODERATORS
 

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

you are viewing a single comment's thread
view the rest of the comments
[โ€“] Deebster 2 points 1 month ago* (last edited 1 month 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);
    }
}