diff --git a/.gitignore b/.gitignore index a7cd375..995429c 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,5 @@ Cargo.lock *.exe -input.txt \ No newline at end of file +data.txt +test-data.txt \ No newline at end of file diff --git a/day02/Cargo.toml b/day02/Cargo.toml new file mode 100644 index 0000000..b35f8a3 --- /dev/null +++ b/day02/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "day02" +version = "0.1.0" +edition = "2021" + +[dependencies] +regex = "1.11.1" diff --git a/day02/src/main.rs b/day02/src/main.rs new file mode 100644 index 0000000..137230e --- /dev/null +++ b/day02/src/main.rs @@ -0,0 +1,117 @@ +// Day 02: Red-Nosed Reports + +use std::fs::File; +use std::io::{self, BufRead}; +use std::path::Path; +use regex::Regex; + +const FILE_NAME: &str = "./data.txt"; + +enum Direction { + Unknown, + Increasing, + Decreasing +} + +fn solve() { + println!("Day 02: Part 1"); + println!("GOAL: Analyze the unusual data from the engineers."); + println!("ANSWER: How many reports are safe?"); + + let mut valid_reports = 0; + + let re_split = Regex::new(r"(\s+)").expect("Invalid regex"); + if let Ok(lines) = read_lines(FILE_NAME) { + for line in lines.flatten() { + let values: Vec<_> = re_split.split(&line).map(|f| f.parse::().unwrap()).collect(); + + let is_valid = is_valid_report(&values); + + // println!("Report {} {} valid", line, if is_valid { "is" } else { "is NOT" }); + + if is_valid { + valid_reports += 1; + } + } + } + println!("Valid reports = {valid_reports}"); + + println!("-----------"); + println!("Day 02: Part 2"); + println!("GOAL: Update your analysis by handling situations where the Problem Dampener can remove a single level from unsafe reports."); + println!("ANSWER: How many reports are now safe?"); + + valid_reports = 0; + if let Ok(lines) = read_lines(FILE_NAME) { + for line in lines.flatten() { + let values: Vec<_> = re_split.split(&line).map(|f| f.parse::().unwrap()).collect(); + + let is_valid = is_any_valid_report(&values); + + println!("Report {} {} valid", line, if is_valid { "is" } else { "is NOT" }); + + if is_valid { + valid_reports += 1; + } + } + } + println!("Valid reports = {valid_reports}"); + +} + +fn is_valid_report (values: &Vec) -> bool { + let mut direction = Direction::Unknown; + // println!("Checking values {:?}", values); + let mut last_report = *values.first().unwrap(); + + for r in &values[1..] { + let report = *r; + + if matches!(direction, Direction::Unknown) { + direction = + if report > last_report { Direction::Increasing } + else { Direction::Decreasing }; + } + + if report == last_report { return false; }; + if matches!(direction, Direction::Increasing) && (report < last_report || report > last_report + 3) { return false }; + if matches!(direction, Direction::Decreasing) && (report > last_report || report + 3 < last_report) { return false }; + + last_report = report; + }; + + return true; +} + +fn is_any_valid_report (values: &Vec) -> bool { + if is_valid_report(values) { return true; } + let length = values.len(); + for idx in 0..length { + if is_valid_report(©_except(values, idx)) { return true; } + } + + return false; +} + +fn copy_except (values: &Vec, exclude_idx: usize) -> Vec { + let mut new_values: Vec = Vec::new(); + let mut idx = 0; + for value in values { + if idx != exclude_idx { + new_values.push(*value); + } + idx += 1; + } + // println!("copied new values {:?}", new_values); + return new_values; +} + +fn main() { + solve(); +} + +fn read_lines

(filename: P) -> io::Result>> +where P: AsRef, { + let file = File::open(filename)?; + Ok(io::BufReader::new(file).lines()) +} diff --git a/main.rs.template b/main.rs.template index e0c8265..a3d2132 100644 --- a/main.rs.template +++ b/main.rs.template @@ -1,12 +1,20 @@ // Day #DAY#: #TITLE# -use std::env; -use std::fs; +use std::fs::File; +use std::io::{self, BufRead}; +use std::path::Path; +use regex::Regex; fn solve_part1() { println!("Day #DAY#: Part 1"); println!("GOAL: #GOAL1#"); - println!("ANSWER: #ANSWER1#"); + println!("ANSWER: #ANSWER1#"); + + if let Ok(lines) = read_lines("./data.txt") { + for line in lines.flatten() { + ... + } + } } fn solve_part2 () { @@ -18,4 +26,10 @@ fn solve_part2 () { fn main() { solve_part1() solve_part2() -} \ No newline at end of file +} + +fn read_lines

(filename: P) -> io::Result>> +where P: AsRef, { + let file = File::open(filename)?; + Ok(io::BufReader::new(file).lines()) +} diff --git a/makefile b/makefile index e338559..c4a0071 100644 --- a/makefile +++ b/makefile @@ -5,6 +5,7 @@ init: cargo new day$(day) sed 's/#DAY#/$(day)/g' main.rs.template | sed 's/#TITLE#/$(title)/g' > day$(day)/src/main.rs touch day$(day)/data.txt + cd day$(day) && cargo add regex build: cd ./day$(day) && cargo build