Advent of Code '24 — Day 1

We're back again with Advent of Code — one of my favourite times of year. Partly for the puzzles, and partly because it's a sign the year is winding up. Like 24 ways to impress your friends and UXmas before it, Advent of Code is an advent calendar, where each day is a pair of code challenges. There's usually some kind of narrative that ties the puzzles together, which ends up adding a fun christmas-y spin to the whole thing.

Usually, I try and do it in a programming language I am not super familiar with, but this year I'm going to stick to Ruby ~~(mainly because I am out of ideas for languages to try 😆)~~ (mainly because we have a newborn on our hands and my brain power is limited!).

Link to puzzle

Part 1

The first part was nice and simple. The challenge was to arrange two lists of numbers, find the difference between lowest number in each list, then the next lowest, then the next lowest (and so on). Then sum the differences between them to get your answer

E.g. given:

3   4
4   3
2   5
1   3
3   9
3   3

The smallest number on the left list is 1, and on the right it is 3. Then 2 and 3 and so on — eventually giving 11

My solution was as follows

list = {left: [], right: []}
    input
      .map { |line| line.split(" ") }
      .each_with_object(list) { |item, memo|
        memo[:left] << Integer(item[0])
        memo[:right] << Integer(item[1])
      }
    sorted_left = list[:left].sort
    sorted_right = list[:right].sort

    sorted_left.each_with_index.map do |left, idx|
      [left, sorted_right[idx]].sort.reverse.inject(:-)
    end.inject(:+)

First creating the left and right lists as arrays, then sorting them, and then finally iterating over the left list to find the corresponding lowest number in the right list and doing the math™.

⭐️ Success!

Part 2

The second part was just as simple.

We needed to find a "similarity score" between the two lists. This was done by multiplying each number in the left list, by the number of times it appears in the right list. Then summing all of those numbers.

Thankfully, Ruby's tally makes it easy to build a histogram given some array of input.

Here's my solution for part 2:

list = {left: [], right: []}
    input
      .map { |line| line.split(" ") }
      .each_with_object(list) { |item, memo|
        memo[:left] << Integer(item[0])
        memo[:right] << Integer(item[1])
      }

right_frequency = list[:right].tally

list[:left].map do |left|
      (right_frequency[left] || 0) * left
    end.inject(:+)  

Building up a list again as step one, then calculating the frequency of each number in step 2.

Before finally doing the math across each number in the left list.

⭐️ Success!

Performance

Pretty quick for a simple puzzle — though I can see some optimisations in my solution (like not needing the initial hash of array), but I'll save that golfing for future puzzles that are bound to take minutes or hours ;)

day 01
├─ part 1 — 0.000542s
╰─ part 2 — 0.000324s

Day one: https://github.com/dNitza/advent-of-code/tree/main/2024/01

Published

by Daniel Nitsikopoulos

in posts

Tagged

© 2010 - 2024 Daniel Nitsikopoulos. All rights reserved.

🕸💍  →