advent-of-code/2024/day2/src/main.rs

93 lines
2.9 KiB
Rust

fn read_input() -> Vec<Vec<i32>> {
let string = std::fs::read_to_string("./input.txt").unwrap();
string
.lines()
.map(|line| {
line.split_whitespace()
.map(|val| val.parse().unwrap())
.collect()
})
.collect()
}
fn find_unsafe(report: &Vec<i32>) -> Option<usize> {
let mut last_value = report[0];
let mut increment = 0;
// the current increment between two values. Mainly for tracking the direction of travel of the series
for (idx, current_value) in report.iter().enumerate().skip(1) {
let difference = current_value - last_value;
if increment * difference < 0 // i.e. difference & increment have different signs
|| difference.abs() < 1
|| difference.abs() > 3
{
return Some(idx);
}
last_value = *current_value;
increment = difference;
}
None
}
fn task1() {
let reports = read_input();
let mut safe_reports = 0;
let mut unsafe_reports = 0;
for report in reports.iter() {
if find_unsafe(report).is_none() {
safe_reports += 1;
} else {
unsafe_reports += 1;
}
}
println!(
"Task1: Total reports: {}, safe: {}, unsafe: {}",
reports.iter().len(),
safe_reports,
unsafe_reports
);
}
fn task2() {
let reports = read_input();
let mut safe_reports = 0;
let mut unsafe_reports = 0;
let total = reports.len();
for report in reports.into_iter() {
match find_unsafe(&report) {
Some(idx) => {
// got to check three cases here: removing the last item of the failed partial sequence, the one before or the one before that (to account for pattern
// like 3, 2, 3, 4, 5 at the start of a pattern, which becomes valid when removing index 0, but we'll only notice the issue at position 2)
let has_safe = 'safe_check: {
// make sure we don't actually access before the vector if the first gap is already invalie
for i in 0..std::cmp::min(3, idx + 1) {
// remove the potentially unsafe item check if that makes it safe
let mut modified_report = report.clone();
modified_report.splice(idx - i..idx - i + 1, []);
if find_unsafe(&modified_report).is_none() {
safe_reports += 1;
break 'safe_check true;
}
}
false
};
if !has_safe {
unsafe_reports += 1;
}
}
None => {
safe_reports += 1;
}
}
}
println!(
"Task2: Total reports: {}, safe: {}, unsafe: {}",
total, safe_reports, unsafe_reports
);
}
fn main() {
task1();
task2();
}