How to solve Advent of Code 2022 - Day 3 with Python

How to solve Advent of Code 2022 - Day 3 with Python

If you missed any previous days, click here for all my content about that: Advent of Code, if you want to know why you should participate and try to code the solution for yourself, click here: Advent Of Code 2022 – 7 Reasons why you should participate. If you're here to see the solution of Day 3, continue reading ;)

GitHub Repository

https://github.com/GalaxyInfernoCodes/Advent_Of_Code_2022

I will upload all of my solutions there - in the form of Python (or Scala alternatives) notebooks. You have to use your own input for the "input.txt" since everyone gets their own and everyone needs to provide a different solution based on their input.

Day 3 Puzzle

On day 3 of Advent of Code, we had to organize rucksacks with each line being the contents of each rucksack:

vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw

As always, I read in all lines:

with open('input.txt', 'r') as f:
    lines = f.readlines()
    rucksacks = [entry.strip() for entry in lines]

Part 1

Then iterate over the rucksacks. Each is split in half to get the two compartments. To find the one common item, I used the set-intersection logic, which gives us exactly the common items needed.

To compute the item's score, I used the ASCII value of the character, because conveniently these count up from A to Z. I subtracted the base (ASCII from 'A'), so 'A' would then be 0, then I added the value of 27, because that is what 'A' should be according to the puzzle. Similar for 'a'.

rucksack_sum = 0
for rucksack in rucksacks:
    # split in half 
    first_half = set(rucksack[:len(rucksack)//2])
    second_half = set(rucksack[len(rucksack)//2:])
    # get overlap through set logic (intersection of two sets)
    overlap_char = (first_half.intersection(second_half)).pop()

    # translate to ascii and substract the base ('A' is 65, 'B' is 66 and so on) and add the new base
    if overlap_char.isupper():
        rucksack_sum += ord(overlap_char) - ord('A') + 27
    else:
        rucksack_sum += ord(overlap_char) - ord('a') + 1
rucksack_sum

Part 2

Here we were supposed to check 3 rucksacks at once and again, find the intersection of these. For that I adapted the code slightly and extracted the first 3 rucksacks from the list using .pop() in each iteration.

rucksack_sum = 0
while len(rucksacks) > 0:
    # take out first 3 entries
    first_rucksack = set(rucksacks.pop())
    second_rucksack = set(rucksacks.pop())
    third_rucksack = set(rucksacks.pop())
    # get overlap through set logic (intersection of two sets applied twice)
    overlap_char = ((first_rucksack.intersection(second_rucksack)).intersection(third_rucksack)).pop()

    # translate to ascii and substract the base ('A' is 65, 'B' is 66 and so on) and add the new base
    if overlap_char.isupper():
        rucksack_sum += ord(overlap_char) - ord('A') + 27
    else:
        rucksack_sum += ord(overlap_char) - ord('a') + 1
rucksack_sum

Conclusion

I definitely preferred this one over yesterday's puzzle about Rock, Paper, Scissors :D Using intersection on sets always pleases the mathematician in me. However, the ASCII conversion felt a bit hack-y to me, but a fun flashback to coding C assignments and learning about the integer representation of all characters.