Advent of Code 2024 Day 2 – Red-Nosed Reports

Advent of Code 2024 Day 2 – Red-Nosed Reports

- 10 mins

Day 2: Red-Nosed Reports

Part 1

Today’s puzzle is called “Red-Nosed Reports”. The input for today’s puzzle is a file where each line is a sequence of numbers, and the size of the sequence can be different for every line in the file. This is the example input that was given.

7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9

Each line corresponds to a report with the numbers being the levels for that report. In the example, every report has 5 levels, but in the actual input, the number of levels can be different for each report.

We need to figure out the number of reports that are safe. For a report to be considered safe:

We can determine which reports from the example are safe/unsafe using the above rules:

My Solution

I solved as follows:

My code has some more details than yesterday’s solution, so there’ a bit more to explain.

with open("input.txt", "rb") as f:
    lines = f.readlines()

converted_lines = ((map(int, line.split())) for line in lines)

sum_of_valid_reports_part_1 = reduce(
    lambda sum, report: sum + (1 if validate_report_1(report) else 0),
    converted_lines,
    0,
)
print(f"LOG: {sum_of_valid_reports_part_1 = }")

Breaking down the code:

Now let’s look at the validate_report_1 function which validates each report.

def validate_report_1(report: Iterable[int]) -> bool:
    direction = ""

    for prev, curr in pairwise(report):
        if direction == "":
            if prev > curr:
                direction = "decreasing"
            else:
                direction = "increasing"
        # Adjacent levels can only differ by at least one and at most three
        if (abs(prev - curr) < 1) or (abs(prev - curr) > 3):
            return False
        if direction == "increasing" and prev > curr:
            return False
        if direction == "decreasing" and prev < curr:
            return False
    return True

Breaking down the code:

Now that we have the validate_report_1 function, we can use it to validate each report in the input and count the number of safe reports, which is the answer to part 1.

I’ve only included the relevant parts of the code here, but to see my full solution, you can check out my Advent of Code GitHub repository.

Part 2

For part 2, we can slightly relax the rules for a report to be considered safe.

If removing a single level from the report that would make the report unsafe according to the rules of part 1, then the report is still considered safe.

Looking at the example input again:

7 6 4 2 1
1 2 7 8 9
9 7 6 2 1
1 3 2 4 5
8 6 4 4 1
1 3 6 7 9

Determining which reports are safe/unsafe according to the new rules:

My Solution

My solution for part 2 is less work than part 1, as we can reuse the validate_report_1 function from part 1.

Given that we still need to validate each report as per the rules of part 1, we reuse the validate_report_1 function, but for each report, we try removing each level and check if the report is still safe.

with open("input.txt", "rb") as f:
    lines = f.readlines()

# Need to be able to index the levels for part
# so we must convert the map object to a list
converted_lines = ((list(map(int, line.split())

sum_of_valid_reports_part_2 = reduce(
lambda sum, report: sum + (1 if validate_report_2(report) else 0),
	converted_lines,
	0,
)
print(f"LOG: {sum_of_valid_reports_part_2 = }")

The only change in the code from part 1 is that we also convert the map object to a list so that we can index the levels in the report, which is required for the part 2 validator function.

def validate_report_2(report: list[int]) -> bool:
    possible_reports = (report[:i] + report[i + 1 :] for i in range(len(report)))
    # If any of the reports with one level removed is valid,
    # then the original report is considered safe
    return any(
        validate_report_1(possible_report) for possible_report in possible_reports
    )

Breaking down the code:


That’s it for day 2 of Advent of Code 2024! I hope you enjoyed reading my solution and let’s see how the rest of the month goes!

Vinesh Benny

Vinesh Benny

A Software Engineer learning about different things in life and otherwise