Initiate AoC 2019 in python

This commit is contained in:
Anders Englöf Ytterström 2023-11-21 09:42:24 +01:00 committed by Anders Englöf Ytterström
parent a48f3608b2
commit 133c76a02a
4 changed files with 173 additions and 0 deletions

1
2019-python/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
__pycache__

35
2019-python/README.md Normal file
View file

@ -0,0 +1,35 @@
Advent of Code 2019
===================
Solutions for #aoc2019 in Python 3 (3.11.5).
Help scripts
------------
Display all solved puzzles:
python aoc.py
To bootstrap a new puzzle (creates `input/<day_no>.txt` and `output/day_<day_no>.py`):
python aoc.py <dag_no> "<puzzle_name>"
Manually copy the puzzle input from https://adventofcode.com and paste it in `input/<day_no>.txt`
to start coding.
Solve separate puzzle (replace `XX` with the puzzle number):
python -m output.day_XX
Solve separate puzzle using stdin (replace `XX` with the puzzle number):
xclip -selection clipboard -o | python -m output.day_XX
cat tmpfile | python -m output.day_XX
Execute separate puzzle on file save (replace `XX` with the puzzle number):
ls output/*.py | entr -c -s 'xclip -selection clipboard -o | python -m output.day_XX'
ls output/*.py | entr -c -s 'cat tmpfile | python -m output.day_XX'
ls output/*.py | entr -c -r python -m output.day_XX
(requires `entr` and `xclip`, Mac users can instead use `pbpaste`)

95
2019-python/aoc.py Normal file
View file

@ -0,0 +1,95 @@
import sys
year = 2019
try:
_, day_no, name = sys.argv
except ValueError:
day_no = None
name = None
print(
f"\nAdvent of Code {year}" "\n###################" "\n\nby Anders Englöf Ytterström"
)
if day_no and name:
padded_no = day_no.zfill(2)
print(f"\n- creating output/day_{padded_no}.py")
with open("output/day_{}.py".format(padded_no), "w") as s:
s.write(
f"""
from output import answer, puzzleinput
n = {day_no}
title = "{name}"
@puzzleinput(n)
def parse_input(data):
return data
@answer(1, "Answer is {{}}")
def part_1(data):
return data
@answer(2, "Actually, answer is {{}}")
def part_2(data):
return data
if __name__ == "__main__":
# use dummy data
parsed = \"\"\"
replace me
\"\"\".strip()
# uncomment to instead use stdin
# import fileinput
# parsed = "\\n".join(list(fileinput.input()))
# uncomment to instead use content of input/{padded_no}.txt
# parsed = parse_input()
part_1(parsed)
# part_2(parsed)
""".strip()
+ "\n"
)
print(f"- creating empty input/{day_no.zfill(2)}.txt")
with open("input/{}.txt".format(day_no.zfill(2)), "w") as i:
i.write("")
print(
f"""
Done! start coding.
Puzzle link:
https://adventofcode.com/{year}/day/{day_no}
Puzzle input (copy and paste to input/{day_no.zfill(2)}.txt):
https://adventofcode.com/{year}/day/{day_no}/input
"""
)
exit(0)
from output import headline
for i in [str(n).zfill(2) for n in range(1, 26)]:
try:
day = __import__(
"output.day_{}".format(i),
globals(),
locals(),
["n", "title", "part_1", "part_2", "parse_input"],
0,
)
headline(day.n, day.title)
data = day.parse_input()
day.part_1(data, decorate=True)
day.part_2(data, decorate=True)
except IOError:
pass
except ImportError:
pass

View file

@ -0,0 +1,42 @@
import functools
def puzzleinput(n, **kwargs):
filename = str(n).zfill(2)
trim_input = kwargs.get("trim_input", True)
filepath = f"./input/{filename}.txt"
def decorator_pi(func):
@functools.wraps(func)
def wrapper_pi(*args, **kwargs):
with open(filepath, "r") as f:
data = f.read()
if trim_input:
return func(data.strip(), *args, **kwargs)
return func(data, *args, **kwargs)
return wrapper_pi
return decorator_pi
def answer(part_index, fmt_string):
def decorator_aoc(func):
@functools.wraps(func)
def wrapper_aoc(*args, **kwargs):
decorate = kwargs.get("decorate", False)
answer = func(*args)
if not decorate:
print(answer)
else:
formatted = fmt_string.format(answer)
print(f"[part {part_index}] {formatted}")
return wrapper_aoc
return decorator_aoc
def headline(n, title):
title = f"Day {n}: {title}"
print("\n".join(["", title, "".join("-" for _ in title), ""]))