2025-05-25 13:00:47 -05:00
|
|
|
use std::collections::HashMap;
|
2025-05-25 12:32:05 -05:00
|
|
|
use std::env;
|
2025-05-25 09:17:18 -05:00
|
|
|
use std::error::Error;
|
|
|
|
|
use std::fs::File;
|
2025-05-25 12:32:05 -05:00
|
|
|
use std::io::{BufReader, prelude::*};
|
2025-05-25 09:17:18 -05:00
|
|
|
|
|
|
|
|
fn parse_line(line: &str) -> Result<(i64, i64), Box<dyn Error>> {
|
|
|
|
|
// 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::<i64>()?;
|
|
|
|
|
let second_element = split_line[1].parse::<i64>()?;
|
|
|
|
|
return Ok((first_element, second_element));
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-25 13:00:47 -05:00
|
|
|
/// 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.
|
2025-05-25 12:32:05 -05:00
|
|
|
fn calculate_diff(mut left_list: Vec<i64>, mut right_list: Vec<i64>) -> 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
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-25 13:00:47 -05:00
|
|
|
/// 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<i64>, right_list: Vec<i64>) -> i64 {
|
|
|
|
|
// calculate number of occurrences of each id in right list
|
|
|
|
|
let mut right_occurrences: HashMap<i64, i64> = 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
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-25 09:17:18 -05:00
|
|
|
fn main() -> Result<(), Box<dyn Error>> {
|
|
|
|
|
// Handle command input
|
|
|
|
|
let args: Vec<String> = 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);
|
|
|
|
|
|
2025-05-25 12:32:05 -05:00
|
|
|
let mut left_list: Vec<i64> = Vec::new();
|
|
|
|
|
let mut right_list: Vec<i64> = Vec::new();
|
|
|
|
|
|
|
|
|
|
for line in input_reader.lines() {
|
2025-05-25 09:17:18 -05:00
|
|
|
let line = line?;
|
|
|
|
|
let parsed_line = parse_line(&line)?;
|
2025-05-25 12:32:05 -05:00
|
|
|
//println!("({},{})", parsed_line.0, parsed_line.1);
|
|
|
|
|
left_list.push(parsed_line.0);
|
|
|
|
|
right_list.push(parsed_line.1);
|
2025-05-25 09:17:18 -05:00
|
|
|
}
|
|
|
|
|
|
2025-05-25 13:00:47 -05:00
|
|
|
println!(
|
|
|
|
|
"Difference: {}",
|
|
|
|
|
calculate_diff(left_list.clone(), right_list.clone())
|
|
|
|
|
);
|
|
|
|
|
println!(
|
|
|
|
|
"Similarity: {}",
|
|
|
|
|
calculate_similarity(left_list, right_list)
|
|
|
|
|
);
|
2025-05-25 12:32:05 -05:00
|
|
|
|
2025-05-25 09:17:18 -05:00
|
|
|
return Ok(());
|
2025-05-25 08:15:48 -05:00
|
|
|
}
|