Skip to content

Refactor 2024 #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Dec 7, 2024
Merged
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
18 changes: 4 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,33 +1,23 @@
.PHONY: all clean black flake test solutions

# Default target
all: black flake test solutions clean
all: ruff test solutions clean

# Clean temporary and generated files
clean:
find . \( -type f -name '*.pyc' -or -type d -name '__pycache__' \) -delete
find . \( -type d -name '.eggs' -or -type d -name '*.egg-info' -or -type d -name '.pytest_cache' \) | xargs rm -rf

# Format code using black
black:
black ./src ./tests

# Run flake8 for linting
flake:
flake8 ./src ./tests
ruff:
ruff check .

# Run tests
test:
python3 -m pytest

# Run specific solutions for Advent of Code 2023
solutions:
python3 src/advent_of_code/year_2023/days/1.py --input_file inputs/2023/1.txt --part 1
python3 src/advent_of_code/year_2023/days/1.py --input_file inputs/2023/1.txt --part 2
python3 src/advent_of_code/year_2023/days/2.py --input_file inputs/2023/2.txt
python3 src/advent_of_code/year_2023/days/3.py --input_file inputs/2023/3.txt
python3 src/advent_of_code/year_2023/days/4.py --input_file inputs/2023/4.txt
python3 src/advent_of_code/year_2023/days/6.py --input_file inputs/2023/6.txt
python3 scripts/run_all_solutions.py

.PHONY: new-day-skeleton-files-from-template
new-day-skeleton-files-from-template:
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
3 changes: 1 addition & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
black==23.12.1
flake8==6.1.0
ruff==0.1.9
numpy==1.26.2
pytest==7.4.3
setuptools==68.2.2
48 changes: 48 additions & 0 deletions scripts/run_all_solutions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import os
import re
import subprocess

BASE_DIR = "src/advent_of_code"
YEARS_DIR = os.path.join(BASE_DIR, "year_")
RUN_DAY_SCRIPT = "scripts/run_day.py"
INPUTS_DIR = "inputs"

def discover_and_run_solutions():
# Regex to match "day_<number>.py"
day_pattern = re.compile(r"day_(\d{2})\.py")

for year in sorted(os.listdir(BASE_DIR)):
if year.startswith("year_"):
year_path = os.path.join(BASE_DIR, year)
year_number = year.split("_")[1]

# Look for days in the "days" directory
days_dir = os.path.join(year_path)
for file in sorted(os.listdir(days_dir)):
match = day_pattern.match(file)
if match:
day_number = match.group(1)

# Build input file path
input_file = os.path.join(INPUTS_DIR, f"year_{year_number}", f"{day_number}.dat")
if not os.path.exists(input_file):
print(f"Input file for {year_number} Day {day_number} not found, skipping.")
continue

# Run the solution using run_day.py
try:
print(f"Running {year_number} Day {day_number}...")
subprocess.run(
[
"python3", RUN_DAY_SCRIPT,
"--year", year_number,
"--day", str(int(day_number)), # Remove leading zero for argument
],
check=True
)
print("\n")
except subprocess.CalledProcessError as e:
print(f"Error running {year_number} Day {day_number}: {e}")

if __name__ == "__main__":
discover_and_run_solutions()
44 changes: 44 additions & 0 deletions scripts/run_day.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import importlib
import sys
import argparse

def main():
parser = argparse.ArgumentParser(description="Run a specific Advent of Code solution.")
# parser.add_argument(
# "--input_file",
# required=True,
# type=str,
# help="Path to the input file for the day's solution."
# )
parser.add_argument(
"--year",
required=True,
type=int,
)
parser.add_argument(
"--day",
required=True,
type=str,
)

args = parser.parse_args()
day_zero_padded_str = str(args.day).zfill(2)
input_file = f"inputs/year_{args.year}/{day_zero_padded_str}.dat"

day_module = f"advent_of_code.year_{args.year}.day_{day_zero_padded_str}"

try:
# Dynamically import the module for the specified day
module = importlib.import_module(day_module)
# Run the solution (assumes each solver module has a `main()` function)
if hasattr(module, "main"):
module.main(input_file)
else:
print("man")
print(f"The module {day_module} does not have a 'main(input_file)' function.")
except ModuleNotFoundError:
print(f"Could not find module: {day_module}")
sys.exit(1)

if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from advent_of_code.utils.input_handling import (
read_input,
)

import re

SPELLED_NUMBERS_MAPPING = {
Expand Down Expand Up @@ -90,3 +94,27 @@ def find_indices_of_patterns(line, patterns_to_find):
patterns_and_indices[pattern] = [m.start() for m in matches]

return patterns_and_indices

def run_part(input_data, accept_written_digits):

patterns_to_find = get_patterns(accept_written_digits)
calibration_value_sum = solve_all_calibration_values(input_data, patterns_to_find)
return calibration_value_sum

def main(input_file):
# args = parse_args()
# input = read_input(args.input_file)
input_data = read_input(input_file)

calibration_value_sum = run_part(input_data, accept_written_digits = False)

print(f"Part 1: Solution is {calibration_value_sum}.")

calibration_value_sum = run_part(input_data, accept_written_digits = True)

print(f"Part 2: Solution is {calibration_value_sum}.")



if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from advent_of_code.utils.input_handling import read_input

import re

BAG_CONSTRAINTS = {"red": 12, "green": 13, "blue": 14}
Expand Down Expand Up @@ -52,3 +54,14 @@ def parse_game_string(full_game_str):

def calculate_game_power(max_colour_1, max_colour_2, max_colour_3):
return max_colour_1 * max_colour_2 * max_colour_3


def main(input_file):
input = read_input(input_file)
part_1_solution, part_2_solution = solve_day_2(input)
print(f"Day 2: Part 1 solution is {part_1_solution}.")
print(f"Part 2 solution is {part_2_solution}.")


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from advent_of_code.utils.input_handling import read_input

import re


Expand Down Expand Up @@ -189,3 +191,17 @@ def solve_day_3(input) -> int:
gear_collection = identify_gears(parts_collection, symbol_collection)
sum_of_gear_ratios = calculate_sum_of_gear_ratios(gear_collection)
return (sum_of_part_numbers, sum_of_gear_ratios)



def main(input_file):
input = read_input(input_file)
result_part_1, result_part_2 = solve_day_3(input)
print(
f"Day 3: The sum of part numbers is {result_part_1}. "
f"The sum of gear ratios is {result_part_2}"
)


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from advent_of_code.utils.input_handling import read_input

import re


Expand Down Expand Up @@ -75,3 +77,17 @@ def solve_day_4(input) -> int:
cards_with_copies = compute_copies(cards)
n_scratchcards = sum([card.n_copies for card in cards_with_copies])
return (total_score, n_scratchcards)


def main(input_file):
input = read_input(input_file)
result_part_1, result_part_2 = solve_day_4(input)
print(
f"Day 4: "
f" Total points for part 1 is {result_part_1}. "
f" Total points for part 2 is {result_part_2}. "
)


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from advent_of_code.utils.input_handling import read_input

import math
import re

Expand Down Expand Up @@ -59,3 +61,17 @@ def solve_day_6(input):
races_part_1 = create_races(input, part=1)
races_part_2 = create_races(input, part=2)
return (races_part_1.solve(), races_part_2.solve())


def main(input_file):
input = read_input(input_file)
result_part_1, result_part_2 = solve_day_6(input)
print(
f"Day 6: "
f" Result for part 1 is {result_part_1}. "
f" Result for part 2 is {result_part_2}. "
)


if __name__ == "__main__":
main()
31 changes: 0 additions & 31 deletions src/advent_of_code/year_2023/days/1.py

This file was deleted.

16 changes: 0 additions & 16 deletions src/advent_of_code/year_2023/days/2.py

This file was deleted.

18 changes: 0 additions & 18 deletions src/advent_of_code/year_2023/days/3.py

This file was deleted.

19 changes: 0 additions & 19 deletions src/advent_of_code/year_2023/days/4.py

This file was deleted.

19 changes: 0 additions & 19 deletions src/advent_of_code/year_2023/days/6.py

This file was deleted.

Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
from advent_of_code.year_2023.solvers.day_1_solvers import (
from advent_of_code.year_2023.day_01 import (
convert_str_to_numerical,
get_patterns,
solve_all_calibration_values,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import pytest
from advent_of_code.year_2023.solvers.day_2_solvers import (
from advent_of_code.year_2023.day_02 import (
solve_day_2,
check_game_is_possible,
parse_game_string,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import pytest

from advent_of_code.year_2023.solvers.day_3_solvers import (
from advent_of_code.year_2023.day_03 import (
Part,
Symbol,
check_char_is_number,
Expand Down
Loading
Loading