--- /dev/null
+use std::collections::HashMap;
+
+fn input() -> &'static str {
+ include_str!("../input/day01.txt")
+}
+
+fn parse(input: &str) -> (Vec<u32>, Vec<u32>) {
+ let mut left = vec![];
+ let mut right = vec![];
+ for (i, n) in input.split_whitespace().enumerate() {
+ if i % 2 == 0 {
+ left.push(n.parse::<u32>().unwrap())
+ } else {
+ right.push(n.parse::<u32>().unwrap())
+ }
+ }
+ (left, right)
+}
+
+fn distance(left: &mut [u32], right: &mut [u32]) -> u32 {
+ left.sort();
+ right.sort();
+ left.iter()
+ .zip(right.iter())
+ .map(|(l, r)| l.abs_diff(*r))
+ .sum()
+}
+
+fn similarity(left: &mut [u32], right: &mut [u32]) -> u32 {
+ let mut counts: HashMap<u32, u32> = HashMap::new();
+ for n in right {
+ let count = counts.entry(*n).or_default();
+ *count += 1;
+ }
+ left.iter().map(|n| n * counts.get(n).unwrap_or(&0)).sum()
+}
+
+pub fn part1() {
+ let (mut left, mut right) = parse(input());
+ let d = distance(&mut left, &mut right);
+ println!("Day 1 Part 1: {}", d);
+}
+
+pub fn part2() {
+ let (mut left, mut right) = parse(input());
+ let d = similarity(&mut left, &mut right);
+ println!("Day 1 Part 2: {}", d);
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ const INPUT_STR: &str = concat!("3 4\n", "4 3\n", "2 5\n", "1 3\n", "3 9\n", "3 3");
+
+ #[test]
+ fn test_parse() {
+ assert_eq!(
+ parse(INPUT_STR),
+ (vec![3, 4, 2, 1, 3, 3], vec![4, 3, 5, 3, 9, 3])
+ )
+ }
+
+ #[test]
+ fn test_distance() {
+ let (mut left, mut right) = parse(INPUT_STR);
+ assert_eq!(distance(&mut left, &mut right), 11)
+ }
+
+ #[test]
+ fn test_similarity() {
+ let (mut left, mut right) = parse(INPUT_STR);
+ assert_eq!(similarity(&mut left, &mut right), 31)
+ }
+}