Advent of Code 2022 Python Solutions: Days 1–4
Advent of Code is a yearly programming challenge where we solve small story-based problems and collect stars. I enjoy it because the problems usually start simple and slowly become harder. It is also a nice way to practice Python, problem solving, data structures, and algorithms.
I am not very strong in competitive programming, but I still like trying Advent of Code because it helps me improve step by step. In 2021, I reached Day 16 and sometimes checked hints from places like Reddit when I got stuck. For Advent of Code 2022, I started a little late, but I still wanted to solve the problems and document my approach.
This post contains my Advent of Code 2022 Python solutions for Days 1 to 4. I explain how I prepare input files, how I read the data, and how I solve each part.
My full code is also available in my GitHub repository: Advent of Code solutions.
How I Organize Advent of Code Inputs
For each day, I keep one text file inside the data directory. The file contains two parts:
- the sample test input from the Advent of Code problem page
- my personal puzzle input
I separate both parts using this line:
Split From Here
For example, the file for Day 1 is saved as:
data/day1.txt
The same pattern is used for the other days:
data/day2.txt
data/day3.txt
data/day4.txt
This makes it easy to first test the solution on the sample input. If the sample answer is correct, I run the same code on my actual puzzle input.
Creating Empty Data Files
I used the small script below to create empty input files for the remaining days.
for i in range(2, 26):
with open(f"data/day{i}.txt", "w") as fp:
fp.writelines("Split From Here")
This only needs to be done once. After that, I copy the sample input and actual input into the correct file.
Reader Function for Advent of Code Inputs
This is the helper function I use to read the input for each day.
def get_data(day=1):
"""Return sample and real Advent of Code input as lists.
The input file should be written as:
[sample input]
Split From Here
[actual input]
Parameters
----------
day : int
Advent of Code day number.
Returns
-------
list[list[str]]
A list with two elements:
- data[0] is the sample input
- data[1] is the real puzzle input
"""
file_name = f"data/day{day}.txt"
with open(file_name) as fp:
data = fp.read().strip().split("Split From Here")
data = [d.strip().split("\n") for d in data]
return data
I use data[0] for the sample input and data[1] for the real input.
Day 1: Calorie Counting
Problem link: Advent of Code 2022 Day 1
Day 1 is about finding how many calories each Elf is carrying. Each Elf has a group of numbers, and empty lines separate the groups.
Day 1 Part 1
Question: Find the Elf carrying the most Calories. How many total Calories is that Elf carrying?
import numpy as np
data = get_data(day=1)[1]
ndata = np.array(data)
split_indexes = np.where(ndata == "")[0]
calorie_groups = np.split(ndata, split_indexes)
calories = np.array([
np.delete(group, np.where(group == "")[0]).astype(int).sum()
for group in calorie_groups
])
answer_part_1 = calories.max()
print(answer_part_1)
Answer:
71924
The idea is simple:
- split the input wherever there is an empty line
- convert each group to integers
- calculate the sum for each Elf
- find the maximum sum
Day 1 Part 2
Question: Find the total Calories carried by the top three Elves.
sorted_calories = calories.copy()
sorted_calories.sort()
answer_part_2 = sorted_calories[-3:].sum()
print(answer_part_2)
Answer:
210406
Here, I sort all calorie sums and then add the last three values.
Day 2: Rock Paper Scissors
Problem link: Advent of Code 2022 Day 2
Day 2 is based on Rock Paper Scissors. The first column is the opponent’s move, and the second column has a different meaning depending on the part.
For Part 1:
Ameans RockBmeans PaperCmeans ScissorsXmeans RockYmeans PaperZmeans Scissors
Day 2 Part 1
data = get_data(day=2)
# Response scores:
# X = Rock, Y = Paper, Z = Scissors
response_value = {
"X": 1,
"Y": 2,
"Z": 3,
}
elf_moves = "ABC"
my_moves = "XYZ"
winning_games = [
f"{elf} {me}"
for elf, me in zip(elf_moves, my_moves[1:] + my_moves[:1])
]
losing_games = [
f"{elf} {me}"
for elf, me in zip(elf_moves, my_moves[-1:] + my_moves[:-1])
]
score = 0
for game in data[1]:
score += response_value[game[-1]]
if game in winning_games:
score += 6
elif game in losing_games:
score += 0
else:
score += 3
print(score)
Answer:
10816
In this part, I first add the score for my selected shape. Then I add:
6points for a win3points for a draw0points for a loss
Day 2 Part 2
In Part 2, the second column does not directly represent my move. Instead:
Xmeans I need to loseYmeans I need to drawZmeans I need to win
score = 0
for game in data[1]:
opponent_move = game[0]
expected_result = game[-1]
if expected_result == "Z":
my_move = [k for k in winning_games if opponent_move in k][0][-1]
score += 6
elif expected_result == "X":
my_move = [k for k in losing_games if opponent_move in k][0][-1]
score += 0
else:
my_move = my_moves[elf_moves.index(opponent_move)]
score += 3
score += response_value[my_move]
print(score)
Answer:
11657
This time, I first decide which move I should play to get the required result. Then I calculate the score in the same way as Part 1.
Day 3: Rucksack Reorganization
Problem link: Advent of Code 2022 Day 3
Day 3 is about finding common item types in rucksacks. Lowercase and uppercase letters have different priorities.
The priority list is:
import string
items = string.ascii_lowercase + string.ascii_uppercase
So:
ahas priority1zhas priority26Ahas priority27Zhas priority52
Day 3 Part 1
Each rucksack has two compartments. We need to find the item type that appears in both compartments.
data = get_data(day=3)
score = 0
for rucksack in data[1]:
half_index = len(rucksack) // 2
first_half = rucksack[:half_index]
second_half = rucksack[half_index:]
repeated_items = set(first_half).intersection(set(second_half))
score += sum(items.index(item) + 1 for item in repeated_items)
print(score)
Answer:
8240
I used Python sets here because set.intersection() makes it easy to find common letters.
Day 3 Part 2
In Part 2, the rucksacks are divided into groups of three. We need to find the common item type in each group.
rucksacks = np.array(data[1])
groups = np.split(rucksacks, np.arange(3, len(rucksacks), 3))
score = 0
for group in groups:
common_items = (
set(group[0])
.intersection(set(group[1]))
.intersection(set(group[2]))
)
score += sum(items.index(item) + 1 for item in common_items)
print(score)
Answer:
2587
Again, sets make the solution short and readable.
Day 4: Camp Cleanup
Problem link: Advent of Code 2022 Day 4
Day 4 is about pairs of section ranges. We need to check whether one range fully contains another range, and later whether the two ranges overlap at all.
The input looks like this:
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
Day 4 Part 1
Question: In how many assignment pairs does one range fully contain the other?
data = get_data(day=4)
score = 0
for group in data[1]:
first_range, second_range = group.split(",")
first_start, first_end = map(int, first_range.split("-"))
second_start, second_end = map(int, second_range.split("-"))
first_sections = set(range(first_start, first_end + 1))
second_sections = set(range(second_start, second_end + 1))
if first_sections.issubset(second_sections) or second_sections.issubset(first_sections):
score += 1
print(score)
Answer:
602
Here, I convert both ranges into sets. Then I check if one set is a subset of the other.
Day 4 Part 2
Question: In how many assignment pairs do the ranges overlap at all?
score = 0
for group in data[1]:
first_range, second_range = group.split(",")
first_start, first_end = map(int, first_range.split("-"))
second_start, second_end = map(int, second_range.split("-"))
first_sections = set(range(first_start, first_end + 1))
second_sections = set(range(second_start, second_end + 1))
if first_sections.intersection(second_sections):
score += 1
print(score)
Answer:
891
For this part, I only need to check whether the intersection between both sets is empty or not.
What I Learned
These first four days are a good warm-up for Advent of Code 2022. The main ideas I used were:
- reading and splitting text input
- using lists and NumPy arrays
- sorting values
- working with dictionaries
- using Python sets for intersections and subset checks
The most useful part for me was using sets. They made Day 3 and Day 4 much easier to write and understand.
Final Notes
This post is part of my Advent of Code 2022 Python solutions series. I use these challenges to practice Python and improve my problem-solving skills. Even if I do not finish every day, documenting the process helps me understand the solutions better.
Comments