use std::collections::HashMap; use std::{env, fs}; fn read_input(path: &str) -> String { fs::read_to_string(path).expect("Cannot read file.") } fn parse_input(input: &str) -> (Vec, Vec) { let (mut right, mut left) = input .lines() .filter(|line| !line.is_empty()) .fold((vec![], vec![]), |mut acc, line| { let split = line.trim().split_once(" ").expect("Cannot split line."); acc.0.push( split .0 .parse::() .expect("Cannot parse integer on the left."), ); acc.1.push( split .1 .parse::() .expect("Cannot parse integer on the right."), ); acc }); right.sort(); left.sort(); (left, right) } fn part_1(left: &Vec, right: &Vec) -> i32 { left.iter() .enumerate() .map(|(i, x)| (x - right[i]).abs()) .sum() } fn part_2(left: &Vec, right: &Vec) -> i32 { let mut occur = HashMap::new(); for x in right.iter() { *occur.entry(x).or_insert(0) += 1; } left.iter().map(|x| x * occur.get(x).unwrap_or(&0)).sum() } fn main() { let args: Vec = env::args().collect(); for arg in args.iter().skip(1) { let input = read_input(&arg); let (left, right) = parse_input(&input); println!("[{}]", &arg); println!("\t[Part 1] => Answer is '{}'.", part_1(&left, &right)); println!("\t[Part 2] => Answer is '{}'.", part_2(&left, &right)); } }