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