Skip to content

Commit fefa4d6

Browse files
committed
Added solution for day 25
1 parent 0a02cc1 commit fefa4d6

File tree

3 files changed

+105
-1
lines changed

3 files changed

+105
-1
lines changed

advent2020/day25.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2021 Andrew Krepps
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
24+
import math
25+
26+
from . import util
27+
28+
29+
def parse_input(lines):
30+
assert len(lines) == 2
31+
return int(lines[0]), int(lines[1])
32+
33+
34+
def find_loop_size(subject, modulus, output):
35+
# uses baby-step giant-step algorithm
36+
m = math.ceil(math.sqrt(modulus))
37+
subject_to_j_table = {pow(subject, j, modulus): j for j in range(m)}
38+
gamma = output
39+
subject_to_neg_m = pow(subject, -m, modulus) # requires python 3.8+
40+
for i in range(m):
41+
if gamma in subject_to_j_table.keys():
42+
return i * m + subject_to_j_table[gamma]
43+
gamma = (gamma * subject_to_neg_m) % modulus
44+
return None
45+
46+
47+
def get_part1_answer(lines):
48+
subject = 7
49+
modulus = 20201227
50+
card_public_key, door_public_key = parse_input(lines)
51+
card_loop_size = find_loop_size(subject, modulus, card_public_key)
52+
if card_loop_size is not None:
53+
return pow(door_public_key, card_loop_size, modulus)
54+
door_loop_size = find_loop_size(subject, modulus, door_public_key)
55+
if door_loop_size is not None:
56+
return pow(card_public_key, door_loop_size, modulus)
57+
return None
58+
59+
60+
def run():
61+
lines = util.get_input_file_lines("day25.txt")
62+
print(f"The answer to part 1 is {get_part1_answer(lines)}")
63+
print(f"There is no part 2. Go back to enjoying the holidays!")

main.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
from advent2020 import day22
4848
from advent2020 import day23
4949
from advent2020 import day24
50+
from advent2020 import day25
5051

5152

5253
day_runners = [
@@ -73,7 +74,8 @@
7374
lambda: day21.run(),
7475
lambda: day22.run(),
7576
lambda: day23.run(),
76-
lambda: day24.run()
77+
lambda: day24.run(),
78+
lambda: day25.run()
7779
]
7880

7981

test/test_day25.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2021 Andrew Krepps
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
24+
import unittest
25+
26+
from advent2020.day25 import get_part1_answer
27+
from advent2020.util import get_input_data_lines
28+
29+
30+
data = """
31+
5764801
32+
17807724
33+
"""
34+
35+
36+
class Day25Test(unittest.TestCase):
37+
def test_day25(self):
38+
lines = get_input_data_lines(data)
39+
self.assertEqual(get_part1_answer(lines), 14897079)

0 commit comments

Comments
 (0)