Day 25 (Python)

This commit is contained in:
akp 2020-12-25 12:30:27 +00:00
parent bfd58e36d1
commit ba57fdfe90
No known key found for this signature in database
GPG key ID: D3E7EAA31B39637E
6 changed files with 197 additions and 0 deletions

24
25-comboBreaker/README.md Normal file
View file

@ -0,0 +1,24 @@
# [Day 25: Combo Breaker](https://adventofcode.com/2020/day/25)
Merry Christmas!
That's Advent of Code done for this year. At the time of writing this, I've not gotten all 49 stars up to this point, so I've got no way to get the 50th star. Even so, I feel slightly cheated out of a part two haha.
I might go back and try some of the other challenges from this year that I didn't complete.
<details><summary>Script output</summary>
```
python .\python\ ft
AoC 2020: day 25 - Combo Breaker
Python 3.8.5
Test cases
1.1 pass in 0.0 seconds
Answers
Part 1: 297257 in 7.745995283126831 seconds
Part 2: 0 in 0.0 seconds
```
</details>

14
25-comboBreaker/info.json Normal file
View file

@ -0,0 +1,14 @@
{
"year": "2020",
"day": "25",
"title": "Combo Breaker",
"testCases": {
"one": [
{
"input": "5764801\n17807724",
"expected": 14897079
}
],
"two": []
}
}

View file

@ -0,0 +1,118 @@
import json
import platform
import sys
import time
from rich import print
from partOne import partOne
from partTwo import partTwo
force_time = False
def run_and_time(f):
st = time.time()
x = f()
et = time.time()
return x, et - st
def run_tests(test_cases):
do_tests = True
if len(test_cases) == 0:
do_tests = False
elif len(test_cases["one"]) == 0 and len(test_cases["two"]) == 0:
do_tests = False
if not do_tests:
print("Info: no test cases specified. Skipping tests\n")
return
print("Test cases")
def rt(tcs, f, n):
for i, tc in enumerate(tcs):
readable_test_num = f"{n}.{i+1}"
print(f"Running {readable_test_num}...", end="\r")
expectedInt = tc["expected"]
result, t = run_and_time(lambda: f(str(tc["input"])))
output_string = f"{readable_test_num} "
if result == expectedInt:
output_string += "[green]pass[/green]"
else:
output_string += (
f"[red]fail[/red] (got {result}, expected {expectedInt})"
)
if t > 15 or force_time:
output_string += f" in {t} seconds"
print(output_string + " " * 12)
rt(test_cases["one"], partOne, 1)
rt(test_cases["two"], partTwo, 2)
print()
if __name__ == "__main__":
try:
info = open("info.json").read()
except FileNotFoundError:
print("Error: could not open info.json")
sys.exit(-1)
info = json.loads(info)
year = info["year"]
day = info["day"]
title = info["title"]
print(f"[yellow]AoC {year}[/yellow]: day {day} - {title}")
print(f"Python {platform.python_version()}\n")
try:
challenge_input = open("input.txt").read()
except FileNotFoundError:
print("Error: could not open input.txt")
sys.exit(-1)
if "vis" in sys.argv:
import visualise
print("[green]Running visualisation....[/green]")
visualise.visualise(challenge_input)
sys.exit()
if "ft" in sys.argv:
force_time = True
run_tests(info["testCases"])
if "debug" in sys.argv:
sys.exit()
print("Answers")
print("Running part 1...", end="\r")
output_string = "Part 1: "
x, t = run_and_time(lambda: partOne(challenge_input))
output_string += str(x)
if t > 15 or force_time:
output_string += f" in {t} seconds"
print(output_string + " " * 12)
print("Running part 2...", end="\r")
output_string = "Part 2: "
x, t = run_and_time(lambda: partTwo(challenge_input))
output_string += str(x)
if t > 15 or force_time:
output_string += f" in {t} seconds"
print(output_string + " " * 12)

View file

@ -0,0 +1,5 @@
from typing import List
def parse(instr: str) -> List[int]:
return [int(x) for x in instr.strip().split("\n")]

View file

@ -0,0 +1,34 @@
from common import *
def single_transformation(v:int, subject_number:int=7) -> int:
return (v * subject_number) % 20201227
def transform(loop_size:int, subject_number:int=7) -> int:
v = 1
for _ in range(loop_size):
v = single_transformation(v, subject_number=subject_number)
return v
def find_loop_size(target_pubkey:int) -> int:
c = 0
v = 1
while True:
c += 1
v = single_transformation(v)
if v == target_pubkey:
return c
def partOne(instr: str) -> int:
pubkey_one, pubkey_two = parse(instr)
loop_size_one = find_loop_size(pubkey_one)
loop_size_two = find_loop_size(pubkey_two)
encryption_key = transform(loop_size_two, subject_number=pubkey_one)
assert encryption_key == transform(loop_size_one, subject_number=pubkey_two), "encryption keys do not match"
return encryption_key

View file

@ -0,0 +1,2 @@
def partTwo(instr: str) -> int:
return 0