Day 1: Historian Hysteria
Megathread guidelines
- Keep top level comments as only solutions, if you want to say something other than a solution put it in a new post. (replies to comments can be whatever)
- You can send code in code blocks by using three backticks, the code, and then three backticks or use something such as https://blocks.programming.dev if you prefer sending it through a URL
FAQ
- What is this?: Here is a post with a large amount of details: https://programming.dev/post/22323136
- Where do I participate?: https://adventofcode.com/
- Is there a leaderboard for the community?: We have a programming.dev leaderboard with the info on how to join in this post: https://programming.dev/post/6631465
Rust
Iβm doing it in Rust again this year. I stopped keeping up with it after day 3 last year, so letβs hope I last longer this time around.
Solution Spoiler Alert
use std::collections::HashMap;
use crate::utils::read_lines;
pub fn solution1() {
let (mut id_list1, mut id_list2) = get_id_lists();
id_list1.sort();
id_list2.sort();
let total_distance = id_list1
.into_iter()
.zip(id_list2)
.map(|(left, right)| (left - right).abs())
.sum::<i32>();
println!("Total distance = {total_distance}");
}
pub fn solution2() {
let (id_list1, id_list2) = get_id_lists();
let id_count_map = id_list2
.into_iter()
.fold(HashMap::<_, i32>::new(), |mut map, id| {
*map.entry(id).or_default() += 1i32;
map
});
let similarity_score = id_list1
.into_iter()
.map(|id| id * id_count_map.get(&id).copied().unwrap_or_default())
.sum::<i32>();
println!("Similarity score = {similarity_score}");
}
fn get_id_lists() -> (Vec<i32>, Vec<i32>) {
read_lines("src/day1/input.txt")
.map(|line| {
let mut ids = line.split_whitespace().map(|id| {
id.parse::<i32>()
.expect("Ids from input must be valid integers")
});
(
ids.next().expect("First Id on line must be present"),
ids.next().expect("Second Id on line must be present"),
)
})
.unzip()
}
Part 1 is a sort and a quick loop. Part 2 could be efficient with a lookup table but it was practically instant with a simple non-memoized scan so left it that way.
You are using some interesting techniques there. I never imaged you could use the result of == for adding to a counter.
But how did you handle duplicates in part 2?
This is my third program in ruby after the ruby tutorial and half of the rails tutorial, so donβt expect anything too good from it.
Also i did this today since i had time, i will probably not comment every day.
fyi for lines 14-22 you an use .abs
instead of checking for negatives and .sum
instead of doing it manually. Check my crystal solution to see what I mean
C#
public class Day01 : Solver
{
private ImmutableArray<int> left;
private ImmutableArray<int> right;
public void Presolve(string input)
{
var pairs = input.Trim().Split("\n").Select(line => Regex.Split(line, @"\s+"));
left = pairs.Select(item => int.Parse(item[0])).ToImmutableArray();
right = pairs.Select(item => int.Parse(item[1])).ToImmutableArray();
}
public string SolveFirst() => left.Sort().Zip(right.Sort()).Select((pair) => int.Abs(pair.First - pair.Second)).Sum().ToString();
public string SolveSecond() => left.Select((number) => number * right.Where(v => v == number).Count()).Sum().ToString();
}
Haskell
Plenty of scope for making part 2 faster, but I think simple is best here. Forgot to sort the lists in the first part, which pushed me waaay off the leaderboard.
import Data.List
main = do
[as, bs] <- transpose . map (map read . words) . lines <$> readFile "input01"
print . sum $ map abs $ zipWith (-) (sort as) (sort bs)
print . sum $ map (\a -> a * length (filter (== a) bs)) as