// https://adventofcode.com/2024/day/2 // // run command: `cargo run ./input.txt` use std::env; use std::error::Error; use std::fs::File; use std::io::{BufReader, prelude::*}; use std::str::FromStr; /// Parse a report into a Vec fn parse_report(line: &str) -> Result, ::Err> where T: FromStr, { let parsed_line = line .split(char::is_whitespace) .map(|v| v.parse()) .collect::, _>>()?; Ok(parsed_line) } #[derive(Eq, PartialEq)] enum LevelTransitionState { Asc, Desc, Bad, Dampened, } fn compare_levels(curr_level: i64, next_level: i64) -> LevelTransitionState { let level_diff = next_level - curr_level; // If the diff is 0 or greater than 3, return bad stat if level_diff == 0 || level_diff.abs() > 3 { return LevelTransitionState::Bad; } // If great than zero they are ascending if level_diff > 0 { return LevelTransitionState::Asc; } //Else we're descending return LevelTransitionState::Desc; } fn is_report_safe(report: Vec) -> bool { // Turn the report into a bunch of states for each adjacent pair in the report let report: Vec = report .windows(2) .map(|l| compare_levels(l[0], l[1])) .collect(); // Setup the loop by checking the first start as a special case let mut prev_state = &report[0]; if prev_state == &LevelTransitionState::Bad { return false; } // Check each state for level_state in report[1..].iter() { // If bad, then it's just bad if level_state == &LevelTransitionState::Bad { return false; } // If the states aren't the same as the prev, it must // have changed direction if level_state != prev_state { return false; } // Setup for next iteration prev_state = level_state; } return true; } // let mut modified_report: Vec> = vec![None]; // let mut tmp_report: Vec> = report.iter().map(|v| Some(*v)).collect(); // modified_report.append(&mut tmp_report); // modified_report.push(None); // dbg!(modified_report); // let states = Vec::new(); // for window in modified_report.windows(3) { // let window_tuple = (window[0], window[1], window[2]); // let state = match window_tuple { // (None, Some(curr), Some(next)) => { // let diff = curr // }, // (Some(prev), Some(curr), Some(next)) => (), // (Some(prev), Some(curr), None) => (), // _ => panic!("This should never happen!"), // } // states.push(state); // } fn main() -> Result<(), Box> { // Handle command input let args: Vec = env::args().collect(); if args.len() != 2 { panic!( "{} must be run with a single argument of files name!", &args[0] ) } let input_file_string = &args[1]; let input_file = File::open(input_file_string)?; let input_reader = BufReader::new(input_file); let mut accumulator = 0; for line in input_reader.lines() { let line = line?; let parsed_report: Vec = parse_report(&line)?; if is_report_safe(parsed_report) { accumulator += 1; } } println!("Number of SAFE reports: {}", accumulator); Ok(()) }