Skip to content

Commit b0bdf75

Browse files
Merge pull request #5 from marcelblijleven/feature/add-2015-day-15-to-18
Feature/add 2015 day 15 to 18
2 parents 13cbb48 + a4d02ee commit b0bdf75

File tree

4 files changed

+179
-0
lines changed

4 files changed

+179
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
from typing import List, Dict, Callable
2+
3+
from adventofcode.util.exceptions import SolutionNotFoundException
4+
from adventofcode.util.helpers import solution_timer
5+
from adventofcode.util.input_helpers import get_input_for_day
6+
7+
8+
instructions_funcs: Dict[str, Callable[[int], int]] = {
9+
'hlf r': lambda r: int(r / 2),
10+
'tpl r': lambda r: int(r * 3),
11+
'inc r': lambda r: r + 1,
12+
}
13+
14+
15+
def run_program(input_data: List[str], registers: Dict[str, int]) -> int: # noqa: C901
16+
position = 0
17+
18+
while position < len(input_data):
19+
instruction, content = parse_instruction(input_data[position])
20+
21+
if instruction == 'hlf':
22+
registers[content] = int(registers[content] / 2)
23+
position += 1
24+
elif instruction == 'tpl':
25+
registers[content] = registers[content] * 3
26+
position += 1
27+
elif instruction == 'inc':
28+
registers[content] += 1
29+
position += 1
30+
elif instruction == 'jmp':
31+
position += int(content)
32+
elif instruction == 'jie':
33+
register, jump_size = content.split(', ')
34+
if registers[register] % 2 == 0:
35+
position += int(jump_size)
36+
else:
37+
position += 1
38+
elif instruction == 'jio':
39+
register, jump_size = content.split(', ')
40+
if registers[register] == 1:
41+
position += int(jump_size)
42+
else:
43+
position += 1
44+
else:
45+
raise ValueError(f'invalid instruction received: {instruction}')
46+
47+
return registers['b']
48+
49+
50+
def parse_instruction(line: str) -> tuple[str, str]:
51+
instruction_key, instruction = line.split(' ', 1)
52+
return instruction_key, instruction
53+
54+
55+
@solution_timer(2015, 23, 1)
56+
def part_one(input_data: List[str]):
57+
registers = {'a': 0, 'b': 0}
58+
answer = run_program(input_data, registers)
59+
60+
if not answer:
61+
raise SolutionNotFoundException(2015, 23, 1)
62+
63+
return answer
64+
65+
66+
@solution_timer(2015, 23, 2)
67+
def part_two(input_data: List[str]):
68+
registers = {'a': 1, 'b': 0}
69+
answer = run_program(input_data, registers)
70+
71+
if not answer:
72+
raise SolutionNotFoundException(2015, 23, 2)
73+
74+
return answer
75+
76+
77+
if __name__ == '__main__':
78+
data = get_input_for_day(2015, 23)
79+
part_one(data)
80+
part_two(data)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
from itertools import combinations
2+
from typing import List
3+
4+
import math
5+
6+
from adventofcode.util.exceptions import SolutionNotFoundException
7+
from adventofcode.util.helpers import solution_timer
8+
from adventofcode.util.input_helpers import get_input_for_day
9+
10+
11+
def get_quantum_entanglement(packages: List[int]) -> int:
12+
return math.prod(packages)
13+
14+
15+
def move_packages_into_groups(all_packages: List[int], number_of_groups: int) -> int:
16+
size = sum(all_packages) // number_of_groups
17+
18+
for package_idx in range(len(all_packages)):
19+
entanglements = [get_quantum_entanglement(list(packages)) for packages in
20+
combinations(all_packages, package_idx) if
21+
sum(packages) == size]
22+
23+
if len(entanglements):
24+
return min(entanglements)
25+
26+
raise ValueError('could not find correct quantum entanglement')
27+
28+
29+
@solution_timer(2015, 24, 1)
30+
def part_one(input_data: List[str]):
31+
packages = list(map(int, input_data))
32+
answer = move_packages_into_groups(packages, 3)
33+
34+
if not answer:
35+
raise SolutionNotFoundException(2015, 24, 1)
36+
37+
return answer
38+
39+
40+
@solution_timer(2015, 24, 2)
41+
def part_two(input_data: List[str]):
42+
packages = list(map(int, input_data))
43+
answer = move_packages_into_groups(packages, 4)
44+
45+
if not answer:
46+
raise SolutionNotFoundException(2015, 24, 2)
47+
48+
return answer
49+
50+
51+
if __name__ == '__main__':
52+
data = get_input_for_day(2015, 24)
53+
part_one(data)
54+
part_two(data)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import pytest
2+
from adventofcode.year_2015.day_23_2015 import parse_instruction, run_program, get_input_for_day
3+
4+
5+
def test_part_one():
6+
assert run_program(get_input_for_day(2015, 23), {'a': 0, 'b': 0}) == 255
7+
8+
9+
def test_part_two():
10+
assert run_program(get_input_for_day(2015, 23), {'a': 1, 'b': 0}) == 334
11+
12+
13+
@pytest.mark.parametrize(['line', 'expected'], [
14+
('inc a', ('inc', 'a')),
15+
('tpl a', ('tpl', 'a')),
16+
('jmp +19', ('jmp', '+19')),
17+
('jmp -7', ('jmp', '-7')),
18+
])
19+
def test_parse_instruction(line, expected):
20+
assert parse_instruction(line) == expected
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import pytest
2+
3+
from adventofcode.year_2015.day_24_2015 import get_quantum_entanglement, move_packages_into_groups
4+
5+
test_input = [1, 2, 3, 4, 5, 7, 8, 9, 10, 11]
6+
7+
8+
@pytest.mark.parametrize(['packages', 'expected'], [
9+
([11, 9], 99),
10+
([10, 9, 1], 90),
11+
([10, 8, 2], 160),
12+
([10, 7, 3], 210),
13+
([10, 5, 4, 1], 200),
14+
([10, 5, 3, 2], 300),
15+
([10, 4, 3, 2, 1], 240),
16+
([9, 8, 3], 216),
17+
([9, 7, 4], 252),
18+
])
19+
def test_get_quantum_entanglement(packages, expected):
20+
assert get_quantum_entanglement(packages) == expected
21+
22+
23+
def test_move_packages_into_groups():
24+
assert move_packages_into_groups(test_input, 3) == 99
25+
assert move_packages_into_groups(test_input, 4) == 44

0 commit comments

Comments
 (0)