-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.py
154 lines (132 loc) · 4.71 KB
/
main.py
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
import argparse
import importlib
from pathlib import Path
from typing import Optional
import json_log_formatter
from ddtrace import patch
from tabulate import tabulate
from day_factory.day_factory import DayFactory
from utils.input_retriever import retrieve_input
patch(logging=True)
import logging # noqa: E402
FORMAT = (
"%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] "
"[dd.service=%(dd.service)s dd.env=%(dd.env)s dd.version=%(dd.version)s "
"dd.trace_id=%(dd.trace_id)s dd.span_id=%(dd.span_id)s] "
"- %(message)s"
)
logging.basicConfig(format=FORMAT)
log = logging.getLogger(__name__)
log.level = logging.INFO
NB_MAX_DAY = 25
# Get the number of Day implemented
def process_days(
star: int,
day: Optional[int],
all_days: bool = False,
download_input: bool = False,
update_readme: bool = False,
) -> None:
nb_day = 0
if day is not None:
nb_day = day
else:
for d in range(1, NB_MAX_DAY + 1):
day_name = f"Day{d:02}"
day_file_name = f"days.day_{d:02}"
try:
getattr(importlib.import_module(day_file_name), day_name)
nb_day = d
except ModuleNotFoundError:
break
if nb_day == 0:
raise Exception("No Day implemented")
if download_input:
retrieve_input(nb_day, Path("inputs/problems"))
return
# Print Header
result_title = "Result"
time_title = "Elapsed Time"
headers = ["Day", "Star", result_title, f"{time_title}, ms"]
table = build_table(nb_day, all_days, star, update_readme)
result_str = tabulate(table, tablefmt="github", headers=headers)
# Display results in the console
print(result_str)
if update_readme:
update_results_in_readme(result_str)
def build_table(
nb_day: int, all_days: bool, star: int, update_readme: bool
) -> list[str]:
table = []
day_factory = DayFactory(nb_day)
if not all_days and not update_readme:
day = day_factory.get_day(nb_day)
if star == 1 or star is None:
table.extend(day.process_first_star())
if star == 2 or star is None:
table.extend(day.process_second_star())
else:
for i in range(1, nb_day + 1):
day = day_factory.get_day(i)
table.extend(day.process_first_star())
day = day_factory.get_day(i)
table.extend(day.process_second_star())
if i < nb_day:
table.append("")
return table
def update_results_in_readme(results: str) -> None:
new_results_section_started = False
with open("README.md", "r+") as file:
lines = file.readlines()
file.seek(0) # Go back to the start of the file
file.truncate(0) # Clear the file
for line in lines:
if line.strip() == "## Results":
new_results_section_started = True
file.write(line)
file.write(results + "\n")
elif new_results_section_started and line.startswith("## "):
new_results_section_started = False
if not new_results_section_started:
file.write(line)
if __name__ == "__main__":
# Add arguments
parser = argparse.ArgumentParser(description="Run Advent of Code 2024")
parser.add_argument(
"-v", "--verbose", action="store_true", help="Display debug log"
)
parser.add_argument(
"-s", "--star", type=int, help="Star to process", default=None, choices=[1, 2]
)
group = parser.add_mutually_exclusive_group()
group.add_argument(
"-a", "--all", action="store_true", help="Process all days", default=False
)
group.add_argument(
"-i", "--input", action="store_true", help="Retrieve inputs", default=False
)
group.add_argument(
"-r", "--readme", action="store_true", help="Retrieve inputs", default=False
)
group.add_argument("-d", "--day", type=int, help="Day to proceed", default=None)
args = parser.parse_args()
# Define logger
log_level = logging.DEBUG if args.verbose else logging.INFO
logger = logging.getLogger()
logger.setLevel(log_level)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(log_level)
logger.addHandler(stream_handler)
json_handler = logging.FileHandler(filename="/tmp/aoc.log")
json_handler.setFormatter(json_log_formatter.JSONFormatter())
json_handler.setLevel(log_level)
logger.addHandler(json_handler)
logger.info("Starting Advent of Code 2024")
process_days(
star=args.star,
day=args.day,
all_days=args.all,
download_input=args.input,
update_readme=args.readme,
)
logger.info("Advent of Code 2024 finished")