Skip to content

Commit 8304c7a

Browse files
committed
refactor utility functions
1 parent b685188 commit 8304c7a

File tree

6 files changed

+330
-131
lines changed

6 files changed

+330
-131
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ Calendar | Solutions | Stars | Rust | Python | 🎁
3535
[Advent of Code 2024](https://adventofcode.com/2024) | [Solutions](src/year2024/README.md) | 50⭐ | 25 | 11 | 3
3636
[Advent of Code 2023](https://adventofcode.com/2023) | [Solutions](src/year2023/README.md) | 50⭐ | 25 | 10 | 2
3737
[Advent of Code 2022](https://adventofcode.com/2022) | [Solutions](src/year2022/README.md) | 50⭐ | 25 | 18 | 1
38-
[Advent of Code 2021](https://adventofcode.com/2021) | [Solutions](src/year2021/README.md) | 50⭐ | 25 | 11 |
39-
[Advent of Code 2020](https://adventofcode.com/2020) | [Solutions](src/year2020/README.md) | 50⭐ | 25 | 23 |
38+
[Advent of Code 2021](https://adventofcode.com/2021) | [Solutions](src/year2021/README.md) | 50⭐ | 25 | 11 |
39+
[Advent of Code 2020](https://adventofcode.com/2020) | [Solutions](src/year2020/README.md) | 50⭐ | 25 | 23 |
4040
[Advent of Code 2019](https://adventofcode.com/2019) | [Solutions](src/year2019/README.md) | 50⭐ | 25 | 23 | 2
4141
[Advent of Code 2018](https://adventofcode.com/2018) | [Solutions](src/year2018/README.md) | 50⭐ | 25 | 4 | 1
42-
[Advent of Code 2017](https://adventofcode.com/2017) | [Solutions](src/year2017/README.md) | 50⭐ | 25 | 17 |
43-
[Advent of Code 2016](https://adventofcode.com/2016) | [Solutions](src/year2016/README.md) | 50⭐ | 25 | 0 |
42+
[Advent of Code 2017](https://adventofcode.com/2017) | [Solutions](src/year2017/README.md) | 50⭐ | 25 | 17 |
43+
[Advent of Code 2016](https://adventofcode.com/2016) | [Solutions](src/year2016/README.md) | 50⭐ | 25 | 0 |
4444
[Advent of Code 2015](https://adventofcode.com/2015) | [Solutions](src/year2015/README.md) | 50⭐ | 25 | 5 | 1
4545

4646
## Bonus 🎁

scripts/answers.py

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,15 @@
1616

1717
import requests
1818

19+
# ---------
20+
1921

2022
@lru_cache(maxsize=None)
21-
def aoc_available_puzzles(
22-
year: int | None = None, seconds: float | None = None
23-
) -> t.Union[dict[int, list[int]], list[int]]:
23+
def aoc_available_puzzles_dict(seconds: float | None = None) -> dict[int, list[int]]:
2424
"""
25-
Returns a dict of available puzzles by year or the list of available puzzles for the given year.
25+
Returns a dict of available puzzles by year.
2626
"""
2727

28-
if year is not None:
29-
years = aoc_available_puzzles(seconds=seconds)
30-
return years.get(year, [])
31-
3228
now = time.gmtime(seconds)
3329

3430
# available years
@@ -45,13 +41,63 @@ def aoc_available_puzzles(
4541
last_day = now.tm_mday - 1 if now.tm_hour < 5 else now.tm_mday
4642
else:
4743
last_day = 25
48-
last_day = min(last_day, 25 if year <= 2024 else 12)
44+
last_day = min(last_day, aoc_puzzles_by_year(year))
4945

5046
puzzles[year] = list(range(1, last_day + 1))
5147

5248
return puzzles
5349

5450

51+
def aoc_puzzles_by_year(year: int) -> int:
52+
"""
53+
Returns the maximum number of puzzles for the given year.
54+
"""
55+
if 2015 <= year <= 2024:
56+
return 25
57+
if year >= 2025:
58+
return 12
59+
return 0
60+
61+
62+
def aoc_nb_answers(year: int, day: int) -> int:
63+
"""
64+
Returns the number of answers.
65+
"""
66+
if 1 <= day < aoc_puzzles_by_year(year):
67+
return 2
68+
elif day == aoc_puzzles_by_year(year):
69+
return 1
70+
else:
71+
return 0
72+
73+
74+
def aoc_available_years():
75+
"""
76+
Generator over all available years.
77+
"""
78+
for year in aoc_available_puzzles_dict():
79+
yield year
80+
81+
82+
def aoc_available_days(year: int):
83+
"""
84+
Generator over all available days for the given year.
85+
"""
86+
for year in aoc_available_puzzles_dict().get(year, []):
87+
yield year
88+
89+
90+
def aoc_available_puzzles(filter_year: int = 0):
91+
for year, days in aoc_available_puzzles_dict().items():
92+
if filter_year is not None and filter_year != 0 and filter_year != year:
93+
continue
94+
for day in days:
95+
yield year, day
96+
97+
98+
# ---------
99+
100+
55101
class AocSession:
56102
last_submit_time = 0 # submissions must be at least 5 seconds apart
57103
rootdir = Path(__file__).parent.parent
@@ -165,11 +211,11 @@ def is_available(year, day):
165211
def iter_all(func, b=None):
166212
def wrapper(self, year=None, day=None, *args, **kwargs):
167213
if year is None:
168-
for year in aoc_available_puzzles():
214+
for year in aoc_available_years():
169215
wrapper(self, year, day)
170216
elif day is None:
171217
# iterate over every days
172-
for day in aoc_available_puzzles(year):
218+
for day in aoc_available_days(year):
173219
wrapper(self, year, day)
174220
elif day == 0:
175221
# special case to iterate only on years
@@ -431,7 +477,7 @@ def print_stars(self, year=None, day=None):
431477
def print_stars_year(self, year=None):
432478
@AocSession.iter_all
433479
def iterate(self, year, day):
434-
nb_stars = sum(self.get_stars(year, day) for day in aoc_available_puzzles(year))
480+
nb_stars = sum(self.get_stars(year, day) for day in aoc_available_days(year))
435481
print(f"{self.prefix} Stars for {year}: {nb_stars:2}⭐")
436482

437483
iterate(self, year, 0)
@@ -530,7 +576,7 @@ def make_readme(args):
530576
def readme(self, year, _day):
531577
puzzles = []
532578
now = datetime.now(UTC)
533-
for day in aoc_available_puzzles(year):
579+
for day in aoc_available_days(year):
534580
available_date = datetime(year, 12, day, 5, 0, 0, 0, tzinfo=UTC)
535581
if available_date > now:
536582
continue
@@ -599,7 +645,7 @@ def make_readme_main(args):
599645
@AocSession.iter_all
600646
def parse(self, year, _day):
601647
now = datetime.now(UTC)
602-
for day in aoc_available_puzzles(year):
648+
for day in aoc_available_days(year):
603649
available_date = datetime(year, 12, day, 5, 0, 0, 0, tzinfo=UTC)
604650
if available_date > now:
605651
continue
@@ -639,7 +685,7 @@ def parse(self, year, _day):
639685
total_rust = sum(rust.values())
640686
total_python = sum(python.values())
641687
total_stars = sum(all_stars.values())
642-
current_calendar = max(aoc_available_puzzles())
688+
current_calendar = max(aoc_available_years())
643689

644690
rows = []
645691
for year in sorted(all_stars.keys(), reverse=True):

scripts/inputs.py

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import argparse
44
import time
5-
import typing as t
65
from collections import Counter
76
from functools import lru_cache
87
from pathlib import Path
@@ -25,18 +24,15 @@
2524
CLEAR_EOL = "\033[0K"
2625

2726

27+
# ---------
28+
29+
2830
@lru_cache(maxsize=None)
29-
def aoc_available_puzzles(
30-
year: int | None = None, seconds: float | None = None
31-
) -> t.Union[dict[int, list[int]], list[int]]:
31+
def aoc_available_puzzles_dict(seconds: float | None = None) -> dict[int, list[int]]:
3232
"""
33-
Returns a dict of available puzzles by year or the list of available puzzles for the given year.
33+
Returns a dict of available puzzles by year.
3434
"""
3535

36-
if year is not None:
37-
years = aoc_available_puzzles(seconds=seconds)
38-
return years.get(year, [])
39-
4036
now = time.gmtime(seconds)
4137

4238
# available years
@@ -53,21 +49,63 @@ def aoc_available_puzzles(
5349
last_day = now.tm_mday - 1 if now.tm_hour < 5 else now.tm_mday
5450
else:
5551
last_day = 25
56-
last_day = min(last_day, 25 if year <= 2024 else 12)
52+
last_day = min(last_day, aoc_puzzles_by_year(year))
5753

5854
puzzles[year] = list(range(1, last_day + 1))
5955

6056
return puzzles
6157

6258

6359
def aoc_puzzles_by_year(year: int) -> int:
60+
"""
61+
Returns the maximum number of puzzles for the given year.
62+
"""
6463
if 2015 <= year <= 2024:
6564
return 25
6665
if year >= 2025:
6766
return 12
6867
return 0
6968

7069

70+
def aoc_nb_answers(year: int, day: int) -> int:
71+
"""
72+
Returns the number of answers.
73+
"""
74+
if 1 <= day < aoc_puzzles_by_year(year):
75+
return 2
76+
elif day == aoc_puzzles_by_year(year):
77+
return 1
78+
else:
79+
return 0
80+
81+
82+
def aoc_available_years():
83+
"""
84+
Generator over all available years.
85+
"""
86+
for year in aoc_available_puzzles_dict():
87+
yield year
88+
89+
90+
def aoc_available_days(year: int):
91+
"""
92+
Generator over all available days for the given year.
93+
"""
94+
for year in aoc_available_puzzles_dict().get(year, []):
95+
yield year
96+
97+
98+
def aoc_available_puzzles(filter_year: int = 0):
99+
for year, days in aoc_available_puzzles_dict().items():
100+
if filter_year is not None and filter_year != 0 and filter_year != year:
101+
continue
102+
for day in days:
103+
yield year, day
104+
105+
106+
# ---------
107+
108+
71109
def transpose(m):
72110
rows = range(len(m))
73111
cols = range(len(m[0]))
@@ -88,14 +126,14 @@ def transpose(m):
88126
datadir = Path(__file__).parent.parent / "data"
89127

90128
data = []
91-
for year in aoc_available_puzzles():
129+
for year in aoc_available_years():
92130
values = []
93131

94132
min_inputs = float("inf")
95133
max_inputs = 0
96134
nb_inputs = 0
97135

98-
available_days = aoc_available_puzzles(year)
136+
available_days = aoc_available_days(year)
99137

100138
for day in range(1, 26):
101139
if day > aoc_puzzles_by_year(year):
@@ -158,7 +196,7 @@ def transpose(m):
158196
print(
159197
tabulate.tabulate(
160198
data,
161-
headers=["Day"] + [year for year in aoc_available_puzzles()],
199+
headers=["Day"] + [year for year in aoc_available_years()],
162200
stralign="right",
163201
tablefmt="rounded_outline",
164202
)

0 commit comments

Comments
 (0)