use std::{ fs::File, io::{BufRead as _, BufReader}, }; fn get_lines(name: &str) -> impl Iterator { BufReader::new(File::open(name).unwrap()) .lines() .map(|line| line.unwrap()) } 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}"); } } mod day3 { use std::fs::read_to_string; use regex::Regex; pub fn task1() { let rx = Regex::new(r"mul\((\d{1,3}),(\d{1,3})\)").unwrap(); let mut result: i64 = 0; for c in rx.captures_iter(&read_to_string("input.txt").unwrap()) { let (_, [a, b]) = c.extract(); result += a.parse::().unwrap() * b.parse::().unwrap(); } println!("{result}"); } pub fn task2() { let rx = Regex::new(r"(mul)\((\d{1,3}),(\d{1,3})\)|do()()()\(\)|do(n't)()()\(\)").unwrap(); let mut enabled = true; let mut result: i64 = 0; for c in rx.captures_iter(&read_to_string("input.txt").unwrap()) { let (_, [op, a, b]) = c.extract(); match op { "" => enabled = true, "n't" => enabled = false, "mul" if enabled => { result += a.parse::().unwrap() * b.parse::().unwrap(); } "mul" => {} _ => unreachable!("{op}"), } } println!("{result}"); } } fn main() { // day1::task1(); // day1::task1(); // day2::task1(); // day2::task2(); day3::task1(); day3::task2(); }