Advent 2024 Day 01
By EricMesa
- 6 minutes read - 1097 wordsDecember has finally arrived and with it my favorite activity of the month - Advent of Code! I also wanted to give myself a fun little present this year, so I bought the Dice Envy Advent Calendar. Every day I’ll get a fun new die (or dice!). Scroll below the AoC code to see today’s die.
Advent of Code
Let’s start off with Advent of Code. This year I haven’t done any of the Advent of Code problems ahead of December so I was a bit rusty. One is not often using the same algorithms or libraries for Advent of Code as one does for everyday programming. I started off with Python since that’s my most comfortable language. First you can head over to today’s page to see the prompt. If you’re not solving the problems yourself, you won’t be able to see the prompt for part 2, so in summary:
- Part 1: You have 2 columns of numbers. You need to sort them lowest to highest. Subtract each number in each row. Sum the differences and that’s your answer
- Part 2: Same 2 columns of numbers. You need to count how many times each number appears on the right side. Then you multiply the number from the left column by how many times it appears on the right side. (with a 0 value if it doesn’t appear at all)
Here’s what my solution looked like:
from collections import Counter
def input_per_line(file: str):
"""This is for when each line is an input to the puzzle. The newline character is stripped."""
with open(file, 'r') as input_file:
return [line.rstrip() for line in input_file.readlines()]
if __name__ == '__main__':
locations = input_per_line("../input.txt")
left_side = []
right_side = []
for line in locations:
entries = line.split()
left_side.append(int(entries[0]))
right_side.append(int(entries[1]))
left_side.sort()
right_side.sort()
distances = [abs(right_side[number]-left_item) for number, left_item in enumerate(left_side)]
print(f"The total distance between the lists is {sum(distances)}")
right_side_count = Counter(right_side)
similarity_list = [item * right_side_count[item] for item in left_side]
print(f"The similarity score is {sum(similarity_list)}")
If you’ve been following me long enough you know that except for extreme circumstances where the problem prompt demands it, I don’t optimize my input. I have a bunch of input parsers I’ve written for Python, Go, Ruby, and Haskel based on the usual types of input that Eric Wasl (AoC creator) typically gives us. I mention this because optimizing the parser can usually lead to more efficient/compact code. Usually Day 1 Part 1 doesn’t have any gotchas. If your code works on the sample input it will work on the actual input. This year there was a catch - you needed to take the absolute value of the difference in order to end up with the right answer for part 1. Part 2 was a cakewalk thanks to Python’s built-in Counter function. However, in many languages, just implementing it via a dictionary/map/hash is pretty easy as you will see in my Go code.
// Solution to Advent of Code 2024 Day 01 - Historian Hysteria
package main
import (
"bufio"
"fmt"
"math"
"os"
"slices"
"strconv"
"strings"
)
// MultipleLines returns the input file if it contains multiple lines of text
func MultipleLines(fileName string) ([]string, error) {
inputSlice := make([]string, 0)
file, err := os.Open(fileName)
if err != nil {
return inputSlice, err
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
inputSlice = append(inputSlice, scanner.Text())
}
err = file.Close()
if err != nil {
return inputSlice, err
}
return inputSlice, nil
}
func main() {
lists, err := MultipleLines("../input.txt")
if err != nil {
fmt.Printf("Error%v\n", err)
}
var leftSide []float64
var rightSide []float64
// split the left and right and convert them to ints.
for _, line := range lists {
temp := strings.Fields(line)
left, _ := strconv.ParseFloat(temp[0], 64)
right, _ := strconv.ParseFloat(temp[1], 64)
leftSide = append(leftSide, left)
rightSide = append(rightSide, right)
}
// Take advantage of the new slice sorting in Go. It sorts in place
slices.Sort(leftSide)
slices.Sort(rightSide)
// a new slice to hold the differences
var diff []float64
for index, value := range leftSide {
diff = append(diff, math.Abs(value-rightSide[index]))
}
var sum float64
for _, value := range diff {
sum += value
}
fmt.Printf("The total distance between the lists is %f\n", sum)
// map to hold a count of values in the right side
var counter = make(map[float64]int)
for _, number := range rightSide {
counter[number] += 1
}
var product []float64
for _, number := range leftSide {
product = append(product, number*float64(counter[number]))
}
var productSum float64
for _, number := range product {
productSum += number
}
fmt.Printf("The simlarity score is %f", productSum)
}
The Golang input tends to be longer because Go has less convenience functions. One nice thing is that a few versions ago they added the slices.Sort function (so I don’t need to implement my own sort - what is this, CS 101?). But (unless I’m missing something) there isn’t a sum function as there is in Python, Haskell, and Ruby. (I guess because those languages support functional programming.) Lots of AoC tends to reduce to map,filter,sum (even if the mapping and filtering are very complex) so Go tends to be a bit more verbose in that realm. I had to use floats since the absolute value function uses floats, not ints. To make the Go solution more elegant, I would make a function for summing the slices rather than essentially doing the same thing twice. Depending on how much free time I find myself with today, I might try to code this in Rust as well. We’ll see.
Dice Envy Dice


I was a little unsure of whether I should have bought myself this Advent calendar. It was $75 (almost as much as their $90-ish for a year of mystery dice). Do I really need to satisfy the dice goblin in me? But as soon as I saw today’s die, I felt I had made the right choice. Today’s die is a chonky thing. It is now the largest D20 I own. It’s ever so slighly larger than a green chonky I’d bought from Dice Envy earlier this year. It’s also, interestingly my lightest over-sized D20. It’s not apparent from the angle of the die/the image capture, but the this D20 is also a beautiful die. It has bits of white throughout that give it a perfect “winter wonderland” feel. Perfect for day 1 of an Advent calendar. Think “what would Elsa from Frozen choose as her D20?” and you’ve got a good idea of what it looks like in person. I’m very excited to continue on throughout the month and to take a final photo with all the advent dice together.