Skip to content

Commit dc9f719

Browse files
Merge pull request #62 from marcelblijleven/2024-01
2024 01
2 parents aabb214 + 9918b9a commit dc9f719

File tree

7 files changed

+106
-10
lines changed

7 files changed

+106
-10
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,5 @@ dmypy.json
132132
.idea
133133

134134
# Advent of code related
135-
.session
135+
.setup.json
136136
src/adventofcode/inputs

.setup.json.template

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"user_agent": "github.com/your-username/your-repo",
3+
"session_cookie": "session cookie value"
4+
}
Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
1+
import json
12
import os
3+
from typing import Required, TypedDict
24

35
from httpx import get
46

57
from adventofcode.config import ROOT_DIR
68

79

10+
class Setup(TypedDict):
11+
user_agent: Required[str]
12+
session_cookie: Required[str]
13+
14+
815
def get_input(year: int, day: int):
9-
session = _read_session()
10-
data = _download_input(year, day, session)
16+
"""
17+
Retrieves input from the Advent of Code website for the given year/day.
18+
After retrieving the input, the input is stored in the project.
19+
"""
20+
setup = _read_setup()
21+
data = _download_input(year, day, setup)
1122
_save_input(data, year, day)
1223

1324

14-
def _download_input(year: int, day: int, session: str) -> bytes:
25+
def _download_input(year: int, day: int, setup: Setup) -> bytes:
1526
"""
1627
Downloads the input as text from the advent of code site
1728
"""
18-
cookies = {"session": session}
29+
cookies = {"session": setup["session_cookie"]}
1930
url = f"https://adventofcode.com/{year}/day/{day}/input"
20-
resp = get(url, cookies=cookies)
31+
resp = get(url, cookies=cookies, headers={"User-Agent": setup["user_agent"]})
2132
resp.raise_for_status()
22-
return resp.content # type: ignore
33+
return resp.content
2334

2435

2536
def _save_input(data: bytes, year: int, day: int) -> None:
@@ -32,9 +43,15 @@ def _save_input(data: bytes, year: int, day: int) -> None:
3243
file.write(data)
3344

3445

35-
def _read_session():
36-
target = os.path.join(ROOT_DIR, "../../.session")
46+
def _read_setup() -> Setup:
47+
"""
48+
Reads .setup.json from the projects' root directory
49+
50+
Returns:
51+
Setup: a typed dict
52+
"""
53+
target = os.path.join(ROOT_DIR, "../../.setup.json")
3754
path = os.path.abspath(target)
3855

3956
with open(path) as f:
40-
return f.read()
57+
return json.load(f)
File renamed without changes.
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
from collections import Counter
2+
3+
from adventofcode.registry.decorators import register_solution
4+
from adventofcode.util.exceptions import SolutionNotFoundError
5+
from adventofcode.util.input_helpers import get_input_for_day
6+
7+
8+
def parse_input(input_data: list[str]) -> tuple[list, list]:
9+
left_list: list[int] = []
10+
right_list: list[int] = []
11+
12+
for row in input_data:
13+
left, right = row.split(" ")
14+
left_list.append(int(left))
15+
right_list.append(int(right))
16+
17+
return sorted(left_list), sorted(right_list)
18+
19+
20+
def calculate_distances(data: tuple[list[int], list[int]]) -> int:
21+
total = 0
22+
for left, right in zip(*data, strict=True):
23+
total += abs(left - right)
24+
25+
return total
26+
27+
28+
def calculate_similarity(data: tuple[list[int], list[int]]) -> int:
29+
total = 0
30+
left_list, right_list = data
31+
right_counter = Counter(right_list)
32+
33+
for num in left_list:
34+
total += right_counter[num] * num
35+
36+
return total
37+
38+
39+
@register_solution(2024, 1, 1)
40+
def part_one(input_data: list[str]):
41+
parsed_input = parse_input(input_data)
42+
answer = calculate_distances(parsed_input)
43+
44+
if not answer:
45+
raise SolutionNotFoundError(2024, 1, 1)
46+
47+
return answer
48+
49+
50+
@register_solution(2024, 1, 2)
51+
def part_two(input_data: list[str]):
52+
parsed_input = parse_input(input_data)
53+
answer = calculate_similarity(parsed_input)
54+
55+
if not answer:
56+
raise SolutionNotFoundError(2024, 1, 2)
57+
58+
return answer
59+
60+
61+
if __name__ == "__main__":
62+
data = get_input_for_day(2024, 1)
63+
part_one(data)
64+
part_two(data)

tests/adventofcode/year_2024/__init__.py

Whitespace-only changes.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from adventofcode.year_2024.day_01_2024 import part_one, part_two
2+
3+
test_input = ["3 4", "4 3", "2 5", "1 3", "3 9", "3 3"]
4+
5+
6+
def test_part_one():
7+
assert part_one(test_input) == 11
8+
9+
10+
def test_part_two():
11+
assert part_two(test_input) == 31

0 commit comments

Comments
 (0)