diff --git a/Cargo.lock b/Cargo.lock index aa37fc3..811ea06 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,7 +1,25 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] [[package]] name = "testing" version = "0.1.0" +dependencies = [ + "itertools", +] diff --git a/Cargo.toml b/Cargo.toml index cd969b7..87cb887 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,4 @@ pedantic = "warn" all = "warn" [dependencies] +itertools = "0.13.0" diff --git a/src/main.rs b/src/main.rs index 5c85b13..22ad29c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,42 +1,109 @@ use std::{ - collections::HashMap, fs::File, - io::{BufRead, BufReader}, + io::{BufRead as _, BufReader}, }; -#[allow(dead_code)] -fn day1_1() { - let reader = BufReader::new(File::open("input.txt").unwrap()); - let mut a = Vec::::new(); - let mut b = Vec::::new(); - for line in reader.lines() { - let line = line.unwrap(); - let (a1, b1) = line.trim_end().split_once(" ").unwrap(); - a.push(a1.parse().unwrap()); - b.push(b1.parse().unwrap()); - } - a.sort_unstable(); - b.sort_unstable(); - let result: i32 = a.into_iter().zip(b).map(|(a, b)| (a - b).abs()).sum(); - println!("{result}"); +fn get_lines(name: &str) -> impl Iterator { + BufReader::new(File::open(name).unwrap()) + .lines() + .map(|line| line.unwrap()) } -#[allow(dead_code)] -fn day1_2() { - let reader = BufReader::new(File::open("input.txt").unwrap()); - let mut a = Vec::::new(); - let mut b = HashMap::::new(); - for line in reader.lines() { - let line = line.unwrap(); - let (a1, b1) = line.trim_end().split_once(" ").unwrap(); - a.push(a1.parse().unwrap()); - *b.entry(b1.parse().unwrap()).or_insert(0) += 1; +mod day1 { + use std::collections::HashMap; + + use crate::get_lines; + + #[allow(dead_code)] + pub fn task1() { + let mut a = Vec::::new(); + let mut b = Vec::::new(); + for line in get_lines("input.txt") { + let (a1, b1) = line.trim_end().split_once(" ").unwrap(); + a.push(a1.parse().unwrap()); + b.push(b1.parse().unwrap()); + } + a.sort_unstable(); + b.sort_unstable(); + let result: i32 = a.into_iter().zip(b).map(|(a, b)| (a - b).abs()).sum(); + println!("{result}"); + } + + #[allow(dead_code)] + pub fn task2() { + let mut a = Vec::::new(); + let mut b = HashMap::::new(); + for line in get_lines("input.txt") { + let (a1, b1) = line.trim_end().split_once(" ").unwrap(); + a.push(a1.parse().unwrap()); + *b.entry(b1.parse().unwrap()).or_insert(0) += 1; + } + let result: u32 = a.into_iter().map(|a| a * *b.get(&a).unwrap_or(&0)).sum(); + println!("{result}"); + } +} + +mod day2 { + use itertools::Itertools; + + use crate::get_lines; + + fn safe(iter: impl Iterator) -> bool { + let mut order = None; + for (a, b) in iter.tuple_windows() { + if !(1..4).contains(&(a - b).abs()) { + return false; + } + if order.is_none() { + order = Some(a.cmp(&b)); + } else if order != Some(a.cmp(&b)) { + return false; + } + } + true + } + + fn parse_line(line: &str) -> impl Iterator + '_ { + line.trim() + .split(' ') + .map(|num| num.parse::().unwrap()) + } + + #[allow(dead_code)] + pub fn task1() { + let result = get_lines("input.txt") + .filter(|line| safe(parse_line(line))) + .count(); + println!("{result}"); + } + + #[allow(dead_code)] + pub fn task2() { + let result = get_lines("input.txt") + .filter(|line| { + let numbers = parse_line(line).collect_vec(); + if safe(numbers.iter().copied()) { + return true; + } + let mut test = Vec::with_capacity(numbers.len() - 1); + for i in 0..numbers.len() { + test.extend_from_slice(&numbers[..i]); + test.extend_from_slice(&numbers[i + 1..]); + if safe(test.iter().copied()) { + return true; + } + test.clear(); + } + false + }) + .count(); + println!("{result}"); } - let result: u32 = a.into_iter().map(|a| a * *b.get(&a).unwrap_or(&0)).sum(); - println!("{result}"); } fn main() { - day1_1(); - day1_2(); + // day1::task1(); + // day1::task1(); + day2::task1(); + day2::task2(); }