//https://adventofcode.com/2024/day/1 // // run command: `cargo run ./input.txt` use std::collections::HashMap; use std::env; use std::error::Error; use std::fs::File; use std::io::{BufReader, prelude::*}; fn parse_line(line: &str) -> Result<(i64, i64), Box> { // Split line on whitespace // Expecting "88789 64926" // Should end up with two string, if not something is wrong. let split_line: Vec<_> = line .splitn(2, char::is_whitespace) .map(|elm| elm.trim()) .collect(); // Parse and return our two elements let first_element = split_line[0].parse::()?; let second_element = split_line[1].parse::()?; return Ok((first_element, second_element)); } /// Part 1 /// /// Maybe the lists are only off by a small amount! To find out, pair /// up the numbers and measure how far apart they are. Pair up the /// smallest number in the left list with the smallest number in the /// right list, then the second-smallest left number with the /// second-smallest right number, and so on. /// /// Within each pair, figure out how far apart the two numbers are; /// you'll need to add up all of those distances. For example, if you /// pair up a 3 from the left list with a 7 from the right list, the /// distance apart is 4; if you pair up a 9 with a 3, the distance /// apart is 6. fn calculate_diff(mut left_list: Vec, mut right_list: Vec) -> i64 { // sort lists left_list.sort(); right_list.sort(); let mut accumulator = 0; for (index, left_value) in left_list.iter().enumerate() { let right_value = right_list[index]; let absolute_diff = (left_value - right_value).abs(); accumulator += absolute_diff; } accumulator } /// Part 2 /// /// This time, you'll need to figure out exactly how often each /// number from the left list appears in the right list. Calculate /// a total similarity score by adding up each number in the left /// list after multiplying it by the number of times that number /// appears in the right list. fn calculate_similarity(left_list: Vec, right_list: Vec) -> i64 { // calculate number of occurrences of each id in right list let mut right_occurrences: HashMap = HashMap::new(); for v in right_list { *right_occurrences.entry(v).or_insert(0) += 1; } // Accumulate result let mut accumulator = 0; for v in left_list { accumulator += v * right_occurrences.get(&v).unwrap_or(&0); } accumulator } fn main() -> Result<(), Box> { // Handle command input let args: Vec = env::args().collect(); if args.len() != 2 { panic!( "{} must be run with a single argument of files name!", &args[0] ) } let input_file_string = &args[1]; let input_file = File::open(input_file_string)?; let input_reader = BufReader::new(input_file); let mut left_list: Vec = Vec::new(); let mut right_list: Vec = Vec::new(); for line in input_reader.lines() { let line = line?; let parsed_line = parse_line(&line)?; //println!("({},{})", parsed_line.0, parsed_line.1); left_list.push(parsed_line.0); right_list.push(parsed_line.1); } println!( "Difference (part 1): {}", calculate_diff(left_list.clone(), right_list.clone()) ); println!( "Similarity (part 2): {}", calculate_similarity(left_list, right_list) ); return Ok(()); }