zerosleeps

Since 2010

Advent of Code 2020 day 9

Advent of Code 2020 day 9. This one was good fun. Got myself into a right mess with variable names - overuse of the word “combination”!

from itertools import combinations
from pathlib import Path
import unittest

def get_raw_input():
    return (Path(__file__).parent/'day_09_input.txt').read_text()

def parse_raw_input(raw_input):
    return [int(line.strip()) for line in raw_input.strip().splitlines()]

def combination_options(full_list, end, preample_len):
    return full_list[end-preample_len:end]

def combinations_to_check(combination_options):
    return combinations(combination_options, 2)

def part_one(parsed_input, preample_len):
    i = preample_len
    while len([
        combination
        for combination
        in combinations_to_check(combination_options(parsed_input, i, preample_len))
        if sum(combination) == parsed_input[i]
    ]) != 0:
        i += 1

    return parsed_input[i]

def part_two(parsed_input, preample_len):
    invalid_number = part_one(parsed_input, preample_len)
    i = 0 # First number to check
    j = 2 # Consecutive numbers to check
    while (i + j) < len(parsed_input):
        while sum(parsed_input[i:i+j]) < invalid_number:
            j += 1 # Try a longer sequence

        if sum(parsed_input[i:i+j]) == invalid_number:
            return min(parsed_input[i:i+j]) + max(parsed_input[i:i+j])

        # Increment starting position and reset sequence length
        i += 1
        j = 2

class TestExamples(unittest.TestCase):
    def setUp(self):
        self.example_input = """35
            20
            15
            25
            47
            40
            62
            55
            65
            95
            102
            117
            150
            182
            127
            219
            299
            277
            309
            576"""

    def test_part_one(self):
        self.assertEqual(part_one(parse_raw_input(self.example_input), 5), 127)

    def test_part_one(self):
        self.assertEqual(part_two(parse_raw_input(self.example_input), 5), 62)

if __name__ == '__main__':
    print(f'Part one: {part_one(parse_raw_input(get_raw_input()), 25)}') # 776203571
    print(f'Part two: {part_two(parse_raw_input(get_raw_input()), 25)}') # 104800569