Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/tox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ on: [pull_request]
jobs:
build:
name: Python Tests
runs-on: ubuntu-24.04
runs-on: ubuntu-26.04
strategy:
max-parallel: 4
matrix:
python-version: ['3.14']
python-version: ['3.15']

steps:
- uses: actions/checkout@v7
Expand Down
28 changes: 6 additions & 22 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,15 @@
exclude: ^template/

default_language_version:
python: python3.14
python: python3.15

repos:
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 26.5.1
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.17.1
hooks:
- id: black
language_version: 'python3.13'

- repo: https://github.com/pycqa/flake8
rev: 7.3.0
hooks:
- id: flake8
args: ["--ignore", "E203,W503,E701"]

- repo: https://github.com/PyCQA/isort
rev: 9.0.0a3
hooks:
- id: isort
- id: ruff-check
args: [--fix]
- id: ruff-format

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
Expand All @@ -33,9 +23,3 @@ repos:
- id: check-merge-conflict
- id: debug-statements
language_version: python3

- repo: https://github.com/asottile/pyupgrade
rev: v3.21.2
hooks:
- id: pyupgrade
args: [ "--py314-plus" ]
32 changes: 12 additions & 20 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "adventofcode"
version = "0.1.0"
description = "Advent of Code - Roel Adriaans"
authors = [{ name = "Roel Adriaans", email = "roel@adriaans.org" }]
requires-python = ">=3.14,<3.15"
requires-python = ">=3.15,<3.16"
license = "MIT"
dependencies = [
"anytree>=2.13.0,<3",
Expand All @@ -25,18 +25,15 @@ adventofcode = "adventofcode.main:main"

[dependency-groups]
dev = [
"black>=26.5.1,<27",
"cookiecutter>=2.6.0,<3",
"pytest>=8.4.2,<10",
"pytest-cov>=7.0.0,<8",
"pytest-xdist>=3.8.0,<4",
"python-dotenv>=1.2.4,<2",
"tox>=4.66.0,<5",
"pre-commit>=4.7.0,<5",
"isort>=9.0.2,<10",
"flake8>=7.4.1",
"pep8-naming>=0.15.1",
"bandit>=1.9.2",
"ruff>=0.15.0",
"tox-uv>=1.35.2",
]

Expand Down Expand Up @@ -107,19 +104,14 @@ markers = [
"slow: marks tests as slow (deselect with '-m \"not slow\"')"
]

[tool.black]
force-exclude = '''
/(
\.git
| \.mypy_cache
| \.venv
| _build
| build
| dist
| template
)/
'''
[tool.ruff]
line-length = 88
target-version = "py315"
extend-exclude = ["template"]

[tool.isort]
extend_skip = ["template"]
profile = "black"
[tool.ruff.lint]
select = ["E", "F", "W", "I", "N", "UP", "C90"]
ignore = ["E203", "E501", "E701", "N818", "UP042"]

[tool.ruff.lint.mccabe]
max-complexity = 17
3 changes: 1 addition & 2 deletions src/adventofcode/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ def create_solution(force, year, day):
try:
importlib.import_module(import_path)
except ModuleNotFoundError:
pass
logger.debug(f"{import_path} does not exist, we can continue")
else:
if not force:
Expand Down Expand Up @@ -271,7 +270,7 @@ def submit_result(year, day, part, result):
if result:
print(f"{result}")
else:
print(f"Could not parse content. Raw result:\n{str(r.content)}")
print(f"Could not parse content. Raw result:\n{r.content!s}")


def parse_result(html_doc):
Expand Down
8 changes: 4 additions & 4 deletions src/adventofcode2016/day02.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ def create_grid(self):
self.grid = defaultdict(lambda: defaultdict(int))

def find_location(self, location: str | int) -> XYPoint:
for x in range(0, self.max_x):
for y in range(0, self.max_x):
for x in range(self.max_x):
for y in range(self.max_x):
if self.grid[x][y] == location:
return XYPoint(x, y)
raise ValueError("Location %s not found", location)
Expand Down Expand Up @@ -65,8 +65,8 @@ def create_grid(self):
"""Create a grid"""
super().create_grid()
n = 1
for x in range(0, 3):
for y in range(0, 3):
for x in range(3):
for y in range(3):
self.grid[x][y] = n
n += 1
self.max_x = 3
Expand Down
3 changes: 1 addition & 2 deletions src/adventofcode2016/day03.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import itertools
import re

from adventofcode.utils.abstract import FileReaderSolution
Expand Down Expand Up @@ -41,7 +40,7 @@ def find_triangles(self, input_lines: str) -> list[list[int]]:
transposed = zip(*list_if_sides)
# And now, chain everything together to create one big list again, in groups
# of 3.
grouped = [iter(itertools.chain(*transposed))] * 3
grouped = [iter(*it for it in transposed)] * 3
return zip(*grouped) # type: ignore

def solve(self, input_data: str) -> int:
Expand Down
15 changes: 7 additions & 8 deletions src/adventofcode2016/day07.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,13 @@ def supports_tls(self) -> bool:
def supports_ssl(self) -> bool:
"""Test if IPv7 address supports SSL (super-secret listening)."""
# First, check if any of the chars parts have abba. At least one needs this
address_parts_aba = list(
itertools.chain.from_iterable(
self.has_aba(text) for text in self.address_parts
)
)
hypernet_parts_aba = list(
itertools.chain.from_iterable(self.has_aba(text) for text in self.hypernets)
)
text = ""
address_parts_aba = [
*it for it in self.has_aba(text) for text in self.address_parts
]
hypernet_parts_aba = [
*it for it in self.has_aba(text) for text in self.hypernets
]
matches = itertools.product(address_parts_aba, hypernet_parts_aba)
return any(IPv7.is_inverse(a, b) for a, b in matches)

Expand Down
4 changes: 2 additions & 2 deletions src/adventofcode2016/day08.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ def init_screen(self, x: int, y: int):

def _draw_rect(self, instruction: Instruction):
"""Draw a rectangle, (eg, put pixels on) from 0,0 until x,y in instruction"""
for x in range(0, instruction.x):
for y in range(0, instruction.y):
for x in range(instruction.x):
for y in range(instruction.y):
self.screen[y, x] = True

def _rotate(self, instruction: Instruction):
Expand Down
4 changes: 2 additions & 2 deletions src/adventofcode2016/day10.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def run(self, a: int, b: int) -> int:
output_bin = defaultdict(list)
while True:
# Loop over the robots
for n, bot in self.bots.items():
for bot in self.bots.values():
if a in bot.chips and b in bot.chips:
return bot.number

Expand All @@ -116,7 +116,7 @@ def run(self) -> int:
output_bin = defaultdict(list)
while True:
# Loop over the robots
for n, bot in self.bots.items():
for bot in self.bots.values():
output_data = self.cascade(bot)

for bin_nr, value in output_data.items():
Expand Down
7 changes: 4 additions & 3 deletions src/adventofcode2016/day11.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,13 @@ def list_of_items_from_floor(self, floor: int) -> list[tuple[str]]:
# Move everything except the elevator, if it exists
items.discard("elevator")

combinations = list(
itertools.chain(
combinations = [
*it
for it in (
itertools.combinations(items, 1),
itertools.combinations(items, 2),
)
)
]
# Validate the set in the elevator
valid = [
combination
Expand Down
8 changes: 4 additions & 4 deletions src/adventofcode2016/day12.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class Copy(Instruction, mnemonic="cpy"):

@classmethod
def _parse(cls, instruction: str) -> Instruction:
mnemonic, value, register_1 = instruction.split()
_mnemonic, value, register_1 = instruction.split()
if value.isdecimal():
return Copy(
value=int(value),
Expand All @@ -83,7 +83,7 @@ class Increment(Instruction, mnemonic="inc"):

@classmethod
def _parse(cls, instruction: str) -> Instruction:
mnemonic, register_1 = instruction.split()
_mnemonic, register_1 = instruction.split()
return cls(register_1=register_1)

def execute(self, instance: Computer):
Expand All @@ -95,7 +95,7 @@ class Decrement(Instruction, mnemonic="dec"):

@classmethod
def _parse(cls, instruction: str) -> Instruction:
mnemonic, register_1 = instruction.split()
_mnemonic, register_1 = instruction.split()
return cls(register_1=register_1)

def execute(self, instance: Computer):
Expand All @@ -112,7 +112,7 @@ class JumpNotZero(Instruction, mnemonic="jnz"):

@classmethod
def _parse(cls, instruction: str) -> Instruction:
mnemonic, compare, value = instruction.split()
_mnemonic, compare, value = instruction.split()
if compare.isdecimal():
# jnz 1 5 -> Compare against a static number
return cls(register_2=int(compare), value=int(value))
Expand Down
2 changes: 1 addition & 1 deletion src/adventofcode2016/day13.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def is_pixel_wall(self, location: MazeLocation) -> bool:
if x < 0 or y < 0:
return True
value = x * x + 3 * x + 2 * x * y + y + y * y + self.favourite_number
number_of_1 = bin(value).count("1")
number_of_1 = (value).bit_count()
# Is this number odd or even?
return number_of_1 % 2 == 1

Expand Down
4 changes: 1 addition & 3 deletions src/adventofcode2016/day18.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ def is_safe(above: list) -> bool:
if above[0] == TRAP and above[1] == above[2] == SAFE:
return False
# Only its right tile is a trap.
if above[0] == above[1] == SAFE and above[2] == TRAP:
return False
return True
return not (above[0] == above[1] == SAFE and above[2] == TRAP)

@classmethod
def evolve(cls, input_string: str) -> str:
Expand Down
10 changes: 5 additions & 5 deletions src/adventofcode2018/day02.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from collections import Counter
from collections.abc import Iterable
from functools import lru_cache
from functools import cache
from itertools import combinations

from adventofcode.utils.abstract import FileReaderSolution
Expand All @@ -25,7 +25,7 @@ def compute_counts(input_string: str) -> tuple[int, int]:

count_twice = 0
count_thrice = 0
for key, count in letter_counter.items():
for count in letter_counter.values():
if count == 2:
count_twice = 1
if count == 3:
Expand Down Expand Up @@ -59,11 +59,11 @@ def solve(self, input_data: str) -> int:

class Day2PartB(Day2, FileReaderSolution):
@staticmethod
@lru_cache(maxsize=None)
@cache
def compute_distance(word1: str, word2: str) -> int:
"""Compute the distance between two words on positional base"""
difference = 0
for i in range(0, len(word1)):
for i in range(len(word1)):
if word1[i] != word2[i]:
difference += 1
return difference
Expand Down Expand Up @@ -91,7 +91,7 @@ def compute_shortest_distance(input_set: Iterable) -> tuple[tuple[str, str], int
def compute_common_letters(word1: str, word2: str) -> str:
"""Return only the letters that are common at the same place"""
letters: list[str] = []
for i in range(0, len(word1)):
for i in range(len(word1)):
if word1[i] == word2[i]:
letters.append(word1[i])
return "".join(letters)
Expand Down
20 changes: 10 additions & 10 deletions src/adventofcode2018/day03.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ def split_claim_into_sections(self, input_data: str) -> Claim:
raise ValueError(f"String {input_data} could not be processed as a valid Claim")

def make_map(self):
self.map: dict[int, dict] = dict()
for i in range(0, self.square_size):
self.map[i] = dict()
for j in range(0, self.square_size):
self.map: dict[int, dict] = {}
for i in range(self.square_size):
self.map[i] = {}
for j in range(self.square_size):
self.map[i][j] = []

def _parse_claim(self, claim: Claim) -> bool:
Expand All @@ -60,8 +60,8 @@ def parse_claims(self, claims: list[Claim]) -> bool:
return True

def print_map(self):
for i in range(0, self.square_size):
for j in range(0, self.square_size):
for i in range(self.square_size):
for j in range(self.square_size):
claims_on_position = len(self.map[i][j])
if claims_on_position == 0:
print(".", end="")
Expand All @@ -74,8 +74,8 @@ def print_map(self):
def compute_multiple_claims(self) -> int:
"""Compute how many claims are overlapping"""
counter = 0
for i in range(0, self.square_size):
for j in range(0, self.square_size):
for i in range(self.square_size):
for j in range(self.square_size):
if len(self.map[i][j]) > 1:
counter += 1
return counter
Expand All @@ -87,8 +87,8 @@ def compute_unclaimed_id(self) -> int:
"""
valid_claims: list = []
invalid_claims: list = []
for i in range(0, self.square_size):
for j in range(0, self.square_size):
for i in range(self.square_size):
for j in range(self.square_size):
claims_on_position = len(self.map[i][j])
if claims_on_position == 1:
claim_id = self.map[i][j][0]
Expand Down
2 changes: 1 addition & 1 deletion src/adventofcode2018/day04.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def determine_mostasleep(guard_info):
def solve(self, input_data: str) -> int:
log_entries = self.parse_strings(input_data)
guard_info = self.parse_logs(log_entries)
guard_id, minutes_slept = self.determine_mostasleep(guard_info)
guard_id, _minutes_slept = self.determine_mostasleep(guard_info)
most_slept_minute = self.determine_most_asleep_minute(guard_info[guard_id])
result = guard_id * most_slept_minute
return result
Expand Down
2 changes: 1 addition & 1 deletion src/adventofcode2018/day05.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def recude_input(input_string: str) -> str:
# Because this is an recursive function, we run into the a recursion error.
# We increase the recursion limit to make our solution work.
sys.setrecursionlimit(5000)
for position in range(0, len(input_string) - 1):
for position in range(len(input_string) - 1):
letter_1 = input_string[position]
letter_2 = input_string[position + 1]
if letter_1.lower() == letter_2.lower() and letter_1 != letter_2:
Expand Down
Loading
Loading