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

How to solve Advent of Code 2022 - Day 4 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 4, 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 4 Puzzle

On day 4 of Advent of Code, we had to find overlapping ranges in pairs of cleaning assignments to prevent the elves from doing the same task twice. For that we get pairs of ranges such as this (with both ends included in the range):

2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8

As always, I read in all lines:

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

Part 1

For part 1, we should find ranges that completely envelop the other range on the same line.

First, the processing of the input lines is a bit more complex than the previous days. I've used the string-splitting function twice: first splitting on the comma, then splitting each half at the '-'. To compare numbers, we first need to convert the string parts into integers.

Afterwards we can check if one range is completely within the other by checking both the start and end value and simply count those cases.

def is_range_a_in_range_b(range_a, range_b):
    start_a, end_a = map(int, range_a.split('-'))
    start_b, end_b = map(int, range_b.split('-'))
    return start_b <= start_a and end_a <= end_b

number_of_contains = 0
for assignment_pair in assignment_pairs:
    first_range, second_range = assignment_pair.split(',')
    if is_range_a_in_range_b(first_range, second_range) or is_range_a_in_range_b(second_range, first_range):
        number_of_contains += 1
number_of_contains    

Part 2

In part 2, the elves decided that they not only care about ranges containing whole other ranges, but instead they care about every single overlap, even if just one number overlaps between the two assignments.

So here I check for 4 cases, either the start or end of the first assignment is within the second assignment or the other way around.

number_of_overlap = 0
for assignment_pair in assignment_pairs:
    first_range, second_range = assignment_pair.split(',')
    start_a, end_a = map(int, first_range.split('-'))
    start_b, end_b = map(int, second_range.split('-'))
    if start_a in range(start_b, end_b+1) or end_a in range(start_b, end_b+1) or  start_b in range(start_a, end_a+1) or end_b in range(start_a, end_a+1):
        number_of_overlap += 1
number_of_overlap    

Conclusion

A lot of number comparisons... Which are not as readable as function calls with describing names. That's partly, why I went for a range comparison in part 2. That, however, has the disadvantage that python range does not include the upper bound unlike the specified puzzle input, so I had to add one to each end. Again, not very clean in my opinion :/