Add solution for 2024 day 02

This commit is contained in:
Patrick Auernig 2024-12-03 18:58:17 +01:00
parent 9ce742fd57
commit 9d2fdf94a5
5 changed files with 1182 additions and 0 deletions

40
2024/day-02/common.rs Normal file
View File

@ -0,0 +1,40 @@
use std::fs;
use std::path::Path;
#[derive(Debug)]
pub struct PuzzleInputs {
pub reports: Vec<Report>,
}
impl PuzzleInputs {
pub fn parse<P>(path: P) -> Self
where
P: AsRef<Path>,
{
let content = fs::read_to_string(path).unwrap();
let mut reports = Vec::new();
for line in content.lines() {
let levels = line.split(' ').map(|x| x.parse().unwrap()).collect();
reports.push(Report { levels });
}
Self { reports }
}
}
#[derive(Debug, Clone)]
pub struct Report {
pub levels: Vec<i32>,
}
impl Report {
pub fn without_index(&self, index: usize) -> Self {
let mut new_report = self.clone();
new_report.levels.remove(index);
new_report
}
}

58
2024/day-02/part_one.rs Normal file
View File

@ -0,0 +1,58 @@
mod common;
use std::env;
use common::{PuzzleInputs, Report};
fn main() {
let input_file = env::args().nth(1).unwrap();
let input = PuzzleInputs::parse(input_file);
let mut num_safe = 0;
for report in &input.reports {
if let Status::Safe = is_report_safe(report) {
num_safe += 1;
}
}
println!("{num_safe}");
}
#[derive(Debug)]
enum Status {
Safe,
Unsafe,
}
fn is_report_safe(report: &Report) -> Status {
let mut order: i32 = 0;
for window in report.levels.windows(2) {
let a = window[0];
let b = window[1];
let diff = b.abs_diff(a);
if diff < 1 || diff > 3 {
return Status::Unsafe;
}
if b > a {
order += 1;
} else {
order -= 1;
}
}
if (order.abs() + 1) != (report.levels.len() as i32) {
return Status::Unsafe;
}
Status::Safe
}

78
2024/day-02/part_two.rs Normal file
View File

@ -0,0 +1,78 @@
mod common;
use std::collections::BTreeSet;
use std::env;
use common::{PuzzleInputs, Report};
fn main() {
let input_file = env::args().nth(1).unwrap();
let input = PuzzleInputs::parse(input_file);
let mut num_safe = 0;
for report in &input.reports {
match is_report_safe(report) {
Status::Safe => {
num_safe += 1;
}
Status::Unsafe(errors) => {
if can_tolerate_error(report, &errors) {
num_safe += 1;
}
}
}
}
println!("{num_safe}");
}
fn can_tolerate_error(report: &Report, errors: &BTreeSet<usize>) -> bool {
for error_idx in errors {
let tmp_report = report.without_index(*error_idx);
if let Status::Safe = is_report_safe(&tmp_report) {
return true;
}
}
false
}
#[derive(Debug)]
enum Status {
Safe,
Unsafe(BTreeSet<usize>),
}
fn is_report_safe(report: &Report) -> Status {
let first = report.levels.first().unwrap();
let last = report.levels.last().unwrap();
let increasing = first < last;
let mut errors = BTreeSet::new();
for (idx, window) in report.levels.windows(2).enumerate() {
let a = window[0];
let a_idx = idx;
let b = window[1];
let b_idx = idx + 1;
let diff = b.abs_diff(a);
if (diff < 1 || diff > 3) || (!increasing && b > a) || (increasing && b < a) {
errors.insert(a_idx);
errors.insert(b_idx);
}
}
if errors.is_empty() {
Status::Safe
} else {
Status::Unsafe(errors)
}
}

1000
2024/day-02/puzzle.txt Normal file

File diff suppressed because it is too large Load Diff

6
2024/day-02/sample.txt Normal file
View File

@ -0,0 +1,6 @@
7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9