60 lines
1.7 KiB
Rust
60 lines
1.7 KiB
Rust
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<i32>, Vec<i32>) {
|
|
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::<i32>()
|
|
.expect("Cannot parse integer on the left."),
|
|
);
|
|
acc.1.push(
|
|
split
|
|
.1
|
|
.parse::<i32>()
|
|
.expect("Cannot parse integer on the right."),
|
|
);
|
|
acc
|
|
});
|
|
right.sort();
|
|
left.sort();
|
|
(left, right)
|
|
}
|
|
|
|
fn part_1(left: &Vec<i32>, right: &Vec<i32>) -> i32 {
|
|
left.iter()
|
|
.enumerate()
|
|
.map(|(i, x)| (x - right[i]).abs())
|
|
.sum()
|
|
}
|
|
|
|
fn part_2(left: &Vec<i32>, right: &Vec<i32>) -> 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<String> = 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));
|
|
}
|
|
}
|