Sean McLemon | Advent of Code

Home | Czech | Blog | GitHub | Advent Of Code | Notes


2024-12-02 - Red-Nosed Reports

(original .ipynb)

Day 2 puzzle input is a list of sequences of integers which represent a series of level readings mine is here). Part 1 involves determining how series of readings (lines of input) are "safe" (no reading is any other than 1-3 higher or lower than the previous, and readings are only ever increasing or decreasing). Part 2 involves doing the same but if removing any one element causes the series to satisfy the rules.

puzzle_input_str = open("./puzzle_input/day2.txt").read()
test_input_str = """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"""


def pairwise(iterable):
    # need to upgrade Python on server, no pairwise in 3.9 :-O
    iterator = iter(iterable)
    a = next(iterator, None)
    for b in iterator:
        yield a, b
        a = b


def parse_line(line_str):
    return [int(s) for s in line_str.split(" ")]


def valid_report(report):
    level_differences = [x-y for x,y in pairwise(report)]
    all_valid = all(abs(diff) >= 1 and abs(diff) <= 3 for diff in level_differences)
    all_increasing = all(diff > 0 for diff in level_differences)
    all_decreasing = all(diff < 0 for diff in level_differences)
    
    return all_valid and (all_increasing or all_decreasing)


def part_one(input_str):
    reports = [parse_line(line) for line in input_str.splitlines()]
    valid_reports = [report for report in reports if valid_report(report)]
    return len(valid_reports)


assert 2 == part_one(test_input_str)

print("part one:", part_one(puzzle_input_str))
part one: 559
def potentially_valid_report(report):
    for i in range(len(report)):
        if valid_report(report[:i] + report[i+1:]):
            return True
    return False


def part_two(input_str):
    reports = [parse_line(line) for line in input_str.splitlines()]
    valid_reports = [report for report in reports if potentially_valid_report(report)]
    return len(valid_reports)


assert 4 == part_two(test_input_str)

print("part two:", part_two(puzzle_input_str))
part two: 601