How to solve Advent of Code 2024 - Day 1 with Python

It's the most festive time of the year - Advent of Code! The highlight of every coder's December. 🎄❄️💻🎉 But before we get right into the first day and my solution for this day's puzzle, here is the info on how I approach this whole event (where my code is, what editor I use, etc):

Day 1 Puzzle
On my blog here, I will go through the puzzle and my way of solving it. If you want, you can jump directly to the code solution here: GitHub .py script
Here is the challenge, if you want to read the full puzzle: https://adventofcode.com/2024/day/1
In summary, on Day 1, we learn that the Chief Historian, who is always present for the big Christmas sleigh launch, has gone missing! A group of Elvish Senior Historians needs our help to find him (someone should have just given him a phone...). To start, they decide to check his office, where they discover scattered notes and lists of location IDs instead of names. The Historians split into two groups to compile a complete list, but their lists don’t match. Now, it’s up to us to help reconcile the differences so we can even start the 25 day search... 😮💨
Part 1
Day 1 gives you an example input text portraying the two lists side by side:
3 4
4 3
2 5
1 3
3 9
3 3
For the solution we want the first and last digit of each line.
To parse the input I always put the text into a .txt
file and read from there. This strategy means I can easily switch between the example
, which is included in the puzzle description and public, including its solution, and the final input
each of us gets (the input should be kept private).
First, I read from this file line by line:
with open(file_path, "r") as f:
lines = f.readlines()
file_lines = [line.strip() for line in lines]
(I also put this in a aoc_utils.py
file and into a function, because we will use something like this again and again and again this year 🔁)
This returns: ['3 4', '4 3', '2 5', '1 3', '3 9', '3 3']
.
I then iterate through each line (double_int_str
) with the following function to extract the integers:
def get_int_pair(double_int_str: str) -> tuple[int, int]:
double_int_str = double_int_str.strip()
left_str, right_str = double_int_str.split()
first_int = int(left_str)
last_int = int(right_str)
return first_int, last_int
Some pointers:
- I
strip()
the line to get rid of any trailing whitespace that I might have copy-pasted from the website. - the
.split()
function by defaults splits on whitespace - which is exactly what is between the first and second number in every line - then simply cast the parts by calling
int()
on them (it's called "type casting" if you want to learn more)
Then iterate through the lines and add the integers to a left and right list:
left_list = []
right_list = []
for line in file_lines:
left_int, right_int = get_int_pair(line)
left_list.append(left_int)
right_list.append(right_int)
Before we can compare the entries (and calculate the difference), they want us to sort them. I just use the built-in sorting from Python's list
.
left_list.sort()
right_list.sort()
We can then use list comprehension and the handy zip
function to calculate the absolute differences between the two lists pairwise:
absolute_diff_list = [
abs(left_int - right_int) for left_int, right_int in zip(left_list, right_list)]
sum(absolute_diff_list)
And the end we just sum up over those differences.
Here's the full solution for part 1:
def solve_part_1(mode: str = "input"):
file_lines = read_input_file(day=1, part=1, mode=mode)
left_list = []
right_list = []
for line in file_lines:
left_int, right_int = get_int_pair(line)
left_list.append(left_int)
right_list.append(right_int)
left_list.sort()
right_list.sort()
absolute_diff_list = [
abs(left_int - right_int) for left_int, right_int in zip(left_list, right_list)
]
return sum(absolute_diff_list)
Part 2
Well, turns out the lists are quite different indeed... 😐 We now need to figure out how often each number of the left list appears in the right list.
Then we compute a similarity score for each entry in the left list:
similarity_score = left_value * nr_of_times_this_value_is_in_the_right_list
In code this means:
similarity_scores = []
for left_int in left_list:
number_of_occurrences = right_list.count(left_int)
similarity_scores.append(left_int * number_of_occurrences)
... then sum up the similarity scores.
The full code for part 2 reuses the parts for building this lists (now in their own build_lists
function):
def solve_part_2(mode: str = "example"):
file_lines = read_input_file(day=1, mode=mode)
left_list, right_list = build_lists(file_lines)
similarity_scores = []
for left_int in left_list:
number_of_occurrences = right_list.count(left_int)
similarity_scores.append(left_int * number_of_occurrences)
return sum(similarity_scores)
Conclusion
So far, so good. This has been quite pleasant, but Day 1 usually is - after you figured out how to parse inputs.
I'm trying my best to write clean-ish code and built reusable functions this year. I am nervous for the coming days. 🫣
No spam, no sharing to third party. Only you and me.
Member discussion