Skip to content

Commit 12cdd54

Browse files
committed
* Set up uv
* Add solution for day 1, 2025
1 parent b82688f commit 12cdd54

8 files changed

Lines changed: 992 additions & 14 deletions

File tree

.pre-commit-config.yaml

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
repos:
2+
- repo: https://gitlab.com/vojko.pribudic.foss/pre-commit-update
3+
rev: v0.9.0
4+
hooks:
5+
# Update pre-commit scripts
6+
- id: pre-commit-update
7+
8+
- repo: https://github.com/astral-sh/uv-pre-commit
9+
rev: 0.9.13
10+
hooks:
11+
# Update the uv lockfile
12+
- id: uv-lock
13+
14+
- repo: https://github.com/asottile/pyupgrade
15+
rev: v3.21.2
16+
hooks:
17+
# Upgrade syntax for newer versions of the language
18+
- id: pyupgrade
19+
args: [--py312-plus]
20+
21+
- repo: https://github.com/pre-commit/pre-commit-hooks
22+
rev: v6.0.0
23+
hooks:
24+
# Prevent giant files from being committed
25+
- id: check-added-large-files
26+
# Check whether files parse as valid python
27+
- id: check-ast
28+
# Require literal syntax for empty or zero Python builtin types
29+
- id: check-builtin-literals
30+
# Check for files with conflict on a case-insensitive filesystem
31+
- id: check-case-conflict
32+
# Checks that non-binary executables have a proper shebang
33+
- id: check-executables-have-shebangs
34+
# Check for files that cannot be created on Windows
35+
- id: check-illegal-windows-names
36+
# Attempts to load all json files to verify syntax
37+
- id: check-json
38+
# Checks that scripts with shebangs are executable
39+
- id: check-shebang-scripts-are-executable
40+
# Checks for symlinks which do not point to anything
41+
- id: check-symlinks
42+
# Attempts to load all TOML files to verify syntax
43+
- id: check-toml
44+
# Attempts to load all yaml files to verify syntax
45+
- id: check-yaml
46+
# Makes sure files end in a newline and only a newline
47+
- id: end-of-file-fixer
48+
# Removes UTF-8 byte order marker
49+
- id: fix-byte-order-marker
50+
# Replaces or checks mixed line ending
51+
- id: mixed-line-ending
52+
# Verifies that test files are named correctly
53+
- id: name-tests-test
54+
args: [--pytest-test-first]
55+
# Protect specific branches from direct checkins
56+
- id: no-commit-to-branch
57+
args: [-b, dev]
58+
# Trims trailing whitespace
59+
- id: trailing-whitespace
60+
61+
- repo: https://github.com/adrienverge/yamllint.git
62+
rev: v1.37.1
63+
hooks:
64+
# Lint YAML files
65+
- id: yamllint
66+
67+
- repo: https://github.com/astral-sh/ruff-pre-commit
68+
rev: v0.14.7
69+
hooks:
70+
# Run the linter
71+
- id: ruff-check
72+
args: [--fix, --show-fixes, --exit-non-zero-on-fix]
73+
# Run the formatter
74+
- id: ruff-format
75+
76+
# local hook used to avoid repeating dependencies list
77+
- repo: local
78+
hooks:
79+
# Check type annotations
80+
- id: mypy
81+
name: mypy
82+
entry: mypy
83+
require_serial: true
84+
language: system
85+
'types_or': [python, pyi]
86+
87+
- repo: https://github.com/fpgmaas/deptry.git
88+
rev: 0.24.0
89+
hooks:
90+
# Check for problems in dependency declarations
91+
- id: deptry
92+
args: ["src"]
93+
94+
- repo: https://github.com/codespell-project/codespell
95+
rev: v2.4.1
96+
hooks:
97+
# Fix common misspellings in text files
98+
- id: codespell
99+
additional_dependencies:
100+
- tomli
101+
102+
- repo: https://github.com/jendrikseipp/vulture
103+
rev: v2.14
104+
hooks:
105+
# Finds unused code
106+
- id: vulture
107+
108+
- repo: https://github.com/pappasam/toml-sort
109+
rev: v0.24.3
110+
hooks:
111+
# Sort and format toml files
112+
- id: toml-sort
113+
args: ["pyproject.toml"]

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# Advent of Code
22

3-
My solutions to [Advent of Code](https://adventofcode.com/) programming puzzles in Python 3.11+.
3+
My solutions to [Advent of Code](https://adventofcode.com/) programming puzzles in Python 3.14.
44

55
Please note that original input to puzzles is not included, it is downloaded dynamically via *advent-of-code-data*
66
library. The sample input files are not original ones, but created by myself.
77

88
## Summary stats
99

10-
| Year | Stars | Days completed |
10+
| Year | Stars | Days completed |
1111
|:----:|:-------------------------------------------------------------------:|:----------------------------------------------------------------:|
1212
| 2025 | ![](https://img.shields.io/badge/2025%20stars%20⭐-0-yellow) | ![](https://img.shields.io/badge/2025%20days%20completed-0-red) |
1313
| 2024 | ![](https://img.shields.io/badge/2024%20stars%20⭐-50-yellow) | ![](https://img.shields.io/badge/2024%20days%20completed-25-red) |

pyproject.toml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[dependency-groups]
2+
dev = [
3+
"deptry",
4+
"graphviz",
5+
"mypy",
6+
"pre-commit",
7+
"pytest",
8+
"pytest-cov",
9+
]
10+
11+
[project]
12+
dependencies = [
13+
"advent-of-code-data",
14+
"matplotlib",
15+
"networkx",
16+
"numpy",
17+
"scipy",
18+
"tqdm",
19+
]
20+
description = "My solutions to Advent of Code programming puzzles."
21+
name = "advent-of-code"
22+
readme = "README.md"
23+
requires-python = ">=3.14"
24+
version = "1.0.0"
25+
26+
[tool.ruff]
27+
indent-width = 4
28+
line-length = 88
29+
target-version = "py312"
30+
31+
[tool.tomlsort]
32+
all = true
33+
in_place = true
34+
trailing_comma_inline_array = true
35+
36+
[tool.vulture]
37+
min_confidence = 80
38+
paths = ["src"]

requirements-to-freeze.txt

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/2025/01/2025_01.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
from enum import Enum
2+
from typing import NamedTuple
3+
4+
from src.utils.data import load_data
5+
from src.utils.submission import submit_or_print
6+
7+
8+
class Direction(Enum):
9+
LEFT = "L"
10+
RIGHT = "R"
11+
12+
def __repr__(self):
13+
return self.value
14+
15+
16+
class Rotation(NamedTuple):
17+
direction: Direction
18+
distance: int
19+
20+
def __repr__(self):
21+
return f"{self.direction!r}{self.distance}"
22+
23+
24+
def main(debug: bool) -> None:
25+
input_data = load_data(debug)
26+
rotations = parse_input(input_data)
27+
28+
limit = 100
29+
initial_position = 50
30+
31+
result_part1 = solve(initial_position, limit, rotations)
32+
result_part2 = solve(initial_position, limit, rotations, part2=True)
33+
34+
submit_or_print(result_part1, result_part2, debug)
35+
36+
37+
def parse_input(input_data: str) -> list[Rotation]:
38+
return [
39+
Rotation(direction=Direction(line[0]), distance=int(line[1:]))
40+
for line in input_data.splitlines()
41+
]
42+
43+
44+
def solve(
45+
init_pos: int, limit: int, commands: list[Rotation], part2: bool = False
46+
) -> int:
47+
print()
48+
result = 0
49+
50+
current_pos = init_pos
51+
for direction, distance in commands:
52+
start_pos = current_pos
53+
54+
# remove all full rotations
55+
quotient, distance = divmod(distance, limit)
56+
57+
# each full rotation goes once through zero
58+
if part2:
59+
result += quotient
60+
61+
# rotate
62+
current_pos += (1 if direction == Direction.RIGHT else -1) * distance
63+
# go back to required range [0, limit)
64+
quotient, current_pos = divmod(current_pos, limit)
65+
66+
# count going through zero if not starting or ending with it
67+
if all([part2, quotient, start_pos != 0, current_pos != 0]):
68+
result += 1
69+
70+
# count ending rotation at zero
71+
if current_pos == 0:
72+
result += 1
73+
74+
return result
75+
76+
77+
if __name__ == "__main__":
78+
debug_mode = True
79+
debug_mode = False
80+
main(debug_mode)

src/2025/01/sample_input.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
R11
2+
L33
3+
R1
4+
L53233
5+
L60

src/utils/submission.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
from typing import Any, Optional
1+
from typing import Any
22

33
from aocd import submit
44

55

6-
def submit_or_print(
7-
result_part1: Optional[Any], result_part2: Optional[Any], debug: bool
8-
):
6+
def submit_or_print(result_part1: Any | None, result_part2: Any | None, debug: bool):
97
print("Result part 1:", result_part1)
108
print("Result part 2:", result_part2)
119
if not debug:

0 commit comments

Comments
 (0)