1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
| 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
|