mirror of
https://github.com/thib8956/advent-of-code.git
synced 2026-11-06 10:02:27 +00:00
chore: create new project structure and aoc.py runner script
This commit is contained in:
1 parent
f76375d835
commit
e2964c6c36
91 files changed
+177
-113
No files matched your search
@@ -1,17 +0,0 @@
|
||||
ran day1/day1.py in 0.016s
|
||||
ran day2/day2.py in 0.021s
|
||||
ran day3/day3.py in 0.017s
|
||||
ran day4/day4.py in 0.039s
|
||||
ran day5/day5.py in 0.191s
|
||||
ran day6/day6.py in 9.655s
|
||||
ran day7/day7.py in 2.227s
|
||||
ran day8/day8.py in 0.017s
|
||||
ran day9/day9.py in 11.159s
|
||||
ran day10/day10.py in 0.052s
|
||||
ran day11/day11.py in 0.116s
|
||||
ran day12/day12.py in 0.170s
|
||||
ran day13/day13.py in 0.014s
|
||||
ran day14/day14.py in 3.729s
|
||||
ran day16/day16.py in 10.082s
|
||||
ran day18/day18.py in 0.872s
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
.PHONY: all venv install clean
|
||||
|
||||
# Define the virtual environment directory
|
||||
VENV_DIR = ./venv
|
||||
|
||||
# Define the Python interpreter to use
|
||||
PYTHON = $(VENV_DIR)/bin/python
|
||||
|
||||
# Default target
|
||||
all: venv install
|
||||
|
||||
# Create virtual environment if it doesn't exist
|
||||
venv:
|
||||
@echo "Creating virtual environment..."
|
||||
@if [ ! -d $(VENV_DIR) ]; then \
|
||||
python3 -m venv $(VENV_DIR); \
|
||||
fi
|
||||
|
||||
install: venv
|
||||
@$(PYTHON) -m pip install --upgrade pip
|
||||
@$(PYTHON) -m pip install -e .
|
||||
|
||||
clean:
|
||||
@echo "Removing virtual environment..."
|
||||
@rm -rf $(VENV_DIR)
|
||||
|
||||
@@ -4,15 +4,25 @@ My solutions to the [advent of code](https://adventofcode.com/) challenges, writ
|
||||
|
||||
## How to run
|
||||
|
||||
### Install project
|
||||
|
||||
Run `make install` or
|
||||
|
||||
Run from root directory (inside a virtualenv):
|
||||
|
||||
```shell
|
||||
$ pip install -e .
|
||||
```
|
||||
|
||||
### Run a single day
|
||||
|
||||
```shell
|
||||
$ python3 run.py <year> <day>
|
||||
$ aoc <year> <day>
|
||||
```
|
||||
|
||||
### Run a whole year
|
||||
|
||||
```shell
|
||||
$ python3 run.py <year>
|
||||
$ aoc <year>
|
||||
```
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Whitespace-only changes.
File renamed without changes.
File renamed without changes.
Whitespace-only changes.
File renamed without changes.
File renamed without changes.
@@ -1,79 +1,79 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
def manhattan_distance(p):
|
||||
return abs(p[0]) + abs(p[1])
|
||||
|
||||
|
||||
def points_for_wire(wire):
|
||||
x, y, count = 0, 0, 0
|
||||
points = {}
|
||||
# (x, y)
|
||||
directions = {"R": (1, 0), "L": (-1, 0), "U": (0, 1), "D": (0, -1)}
|
||||
for p in wire:
|
||||
# D42 -> for _ in range(42)
|
||||
for _ in range(int(p[1:])):
|
||||
offset = directions[p[0]]
|
||||
x += offset[0]
|
||||
y += offset[1]
|
||||
count += 1
|
||||
points[(x ,y)] = count
|
||||
|
||||
return points
|
||||
|
||||
|
||||
def find_min_distance(wire1, wire2):
|
||||
points1 = points_for_wire(wire1)
|
||||
points2 = points_for_wire(wire2)
|
||||
|
||||
intersections = points1.keys() & points2.keys()
|
||||
closest = min((intersection for intersection in intersections), key=manhattan_distance)
|
||||
|
||||
return manhattan_distance(closest)
|
||||
|
||||
|
||||
def find_least_steps(wire1, wire2):
|
||||
points1 = points_for_wire(wire1)
|
||||
points2 = points_for_wire(wire2)
|
||||
|
||||
intersections = points1.keys() & points2.keys()
|
||||
# Intersection with the least steps
|
||||
least_steps = min(intersections, key=lambda x: points1[x] + points2[x])
|
||||
|
||||
return points1[least_steps] + points2[least_steps]
|
||||
|
||||
|
||||
def tests():
|
||||
inputs = (
|
||||
(("R8", "U5", "L5", "D3"), ("U7", "R6", "D4", "L4")),
|
||||
(("R75","D30","R83", "U83", "L12", "D49", "R71", "U7", "L72"), ("U62", "R66", "U55", "R34", "D71", "R55", "D58", "R83")),
|
||||
(("R98", "U47", "R26", "D63", "R33", "U87", "L62", "D20", "R33", "U53", "R51"), ("U98", "R91", "D20", "R16", "D67", "R40", "U7", "R15", "U6", "R7"))
|
||||
)
|
||||
|
||||
# Part 1
|
||||
expected = (6, 159, 135)
|
||||
for i, inp in enumerate(inputs):
|
||||
result = find_min_distance(inp[0], inp[1])
|
||||
assert result == expected[i], "Result for {} should be {}, was {}".format(
|
||||
inp, expected[i], result
|
||||
)
|
||||
|
||||
# Part 2
|
||||
# expected number of steps
|
||||
expected_part2 = (30, 610, 410)
|
||||
print("All tests passed.")
|
||||
for i, inp in enumerate(inputs):
|
||||
result = find_least_steps(inp[0], inp[1])
|
||||
assert result == expected_part2[i], "Result for {} should be {}, was {}".format(
|
||||
inp, expected_part2[i], result
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
tests()
|
||||
import sys
|
||||
infile = sys.argv[1] if len(sys.argv) > 1 else "example.txt"
|
||||
with open(infile) as raw_input:
|
||||
lines = raw_input.readlines()
|
||||
wire1, wire2 = [line.strip("\n").split(",") for line in lines]
|
||||
print("Part 1 -- distance = ", find_min_distance(wire1, wire2))
|
||||
print("Part 2 -- steps = ", find_least_steps(wire1, wire2))
|
||||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
def manhattan_distance(p):
|
||||
return abs(p[0]) + abs(p[1])
|
||||
|
||||
|
||||
def points_for_wire(wire):
|
||||
x, y, count = 0, 0, 0
|
||||
points = {}
|
||||
# (x, y)
|
||||
directions = {"R": (1, 0), "L": (-1, 0), "U": (0, 1), "D": (0, -1)}
|
||||
for p in wire:
|
||||
# D42 -> for _ in range(42)
|
||||
for _ in range(int(p[1:])):
|
||||
offset = directions[p[0]]
|
||||
x += offset[0]
|
||||
y += offset[1]
|
||||
count += 1
|
||||
points[(x ,y)] = count
|
||||
|
||||
return points
|
||||
|
||||
|
||||
def find_min_distance(wire1, wire2):
|
||||
points1 = points_for_wire(wire1)
|
||||
points2 = points_for_wire(wire2)
|
||||
|
||||
intersections = points1.keys() & points2.keys()
|
||||
closest = min((intersection for intersection in intersections), key=manhattan_distance)
|
||||
|
||||
return manhattan_distance(closest)
|
||||
|
||||
|
||||
def find_least_steps(wire1, wire2):
|
||||
points1 = points_for_wire(wire1)
|
||||
points2 = points_for_wire(wire2)
|
||||
|
||||
intersections = points1.keys() & points2.keys()
|
||||
# Intersection with the least steps
|
||||
least_steps = min(intersections, key=lambda x: points1[x] + points2[x])
|
||||
|
||||
return points1[least_steps] + points2[least_steps]
|
||||
|
||||
|
||||
def tests():
|
||||
inputs = (
|
||||
(("R8", "U5", "L5", "D3"), ("U7", "R6", "D4", "L4")),
|
||||
(("R75","D30","R83", "U83", "L12", "D49", "R71", "U7", "L72"), ("U62", "R66", "U55", "R34", "D71", "R55", "D58", "R83")),
|
||||
(("R98", "U47", "R26", "D63", "R33", "U87", "L62", "D20", "R33", "U53", "R51"), ("U98", "R91", "D20", "R16", "D67", "R40", "U7", "R15", "U6", "R7"))
|
||||
)
|
||||
|
||||
# Part 1
|
||||
expected = (6, 159, 135)
|
||||
for i, inp in enumerate(inputs):
|
||||
result = find_min_distance(inp[0], inp[1])
|
||||
assert result == expected[i], "Result for {} should be {}, was {}".format(
|
||||
inp, expected[i], result
|
||||
)
|
||||
|
||||
# Part 2
|
||||
# expected number of steps
|
||||
expected_part2 = (30, 610, 410)
|
||||
print("All tests passed.")
|
||||
for i, inp in enumerate(inputs):
|
||||
result = find_least_steps(inp[0], inp[1])
|
||||
assert result == expected_part2[i], "Result for {} should be {}, was {}".format(
|
||||
inp, expected_part2[i], result
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
tests()
|
||||
import sys
|
||||
infile = sys.argv[1] if len(sys.argv) > 1 else "example.txt"
|
||||
with open(infile) as raw_input:
|
||||
lines = raw_input.readlines()
|
||||
wire1, wire2 = [line.strip("\n").split(",") for line in lines]
|
||||
print("Part 1 -- distance = ", find_min_distance(wire1, wire2))
|
||||
print("Part 2 -- steps = ", find_least_steps(wire1, wire2))
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,14 +1,11 @@
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# TODO replace PYTHONPATH hack with a proper solution, like making intcode an
|
||||
# installed module https://stackoverflow.com/a/50194143
|
||||
sys.path.append(str(Path(__file__).absolute().parent.parent / "intcode"))
|
||||
|
||||
from itertools import cycle, permutations
|
||||
from intcode import interpret_intcode, Interpreter
|
||||
|
||||
|
||||
def main(inp):
|
||||
mem = list(map(int, inp.readline().rstrip().split(",")))
|
||||
max_ret = 0
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,41 @@
|
||||
import argparse
|
||||
from adventofcode.helper import run, get_input_file
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Advent of Code CLI")
|
||||
subparsers = parser.add_subparsers(dest='command')
|
||||
|
||||
# Sous-commande init
|
||||
init_parser = subparsers.add_parser('init', help='Init an aoc day')
|
||||
init_parser.add_argument('year', type=int)
|
||||
init_parser.add_argument('day', type=int)
|
||||
|
||||
# Sous-commande run
|
||||
run_parser = subparsers.add_parser('run', help='Run an aoc day')
|
||||
run_parser.add_argument('year', type=int)
|
||||
run_parser.add_argument('day', type=int)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.command == 'init':
|
||||
handle_init(args.year, args.day)
|
||||
elif args.command == 'run':
|
||||
handle_run(args.year, args.day)
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
|
||||
def handle_init(year, day):
|
||||
# TODO initialize directory if needed, download input file and create
|
||||
# dayX.py from a template
|
||||
raise NotImplementedError("init")
|
||||
|
||||
|
||||
def handle_run(year, day):
|
||||
run(year, day)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
import urllib.request
|
||||
import getpass
|
||||
import sys
|
||||
@@ -6,6 +7,7 @@ import subprocess
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
ROOTPATH = Path(os.path.dirname(os.path.realpath(__file__)))
|
||||
|
||||
_auth = None
|
||||
|
||||
@@ -27,9 +29,9 @@ def get_input_file(year, day):
|
||||
return res
|
||||
|
||||
|
||||
def main(year, day):
|
||||
def run(year, day):
|
||||
if day is not None:
|
||||
path = Path(f"{year}/day{day}")
|
||||
path = ROOTPATH / Path(f"{year}/day{day}")
|
||||
script_path = path / Path(f"day{day}.py")
|
||||
input_path = path / Path("input.txt")
|
||||
if not script_path.exists():
|
||||
@@ -45,7 +47,7 @@ def main(year, day):
|
||||
run_day(script_path, input_path)
|
||||
else:
|
||||
for day in range(1, 26):
|
||||
path = Path(f"{year}/day{day}")
|
||||
path = ROOTPATH / Path(f"{year}/day{day}")
|
||||
script_path = path / Path(f"day{day}.py")
|
||||
input_path = path / Path("input.txt")
|
||||
if script_path.exists():
|
||||
@@ -69,12 +71,3 @@ def run_day(script_path, input_path):
|
||||
except subprocess.TimeoutExpired:
|
||||
print(f"> timeout {script_path} after 30s", file=sys.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) <= 1:
|
||||
print(f"Usage: {__file__} <year> [<day>]", file=sys.stderr)
|
||||
exit(1)
|
||||
year = sys.argv[1]
|
||||
day = sys.argv[2] if len(sys.argv) > 2 else None
|
||||
main(year, day)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
[build-system]
|
||||
requires = ["setuptools"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "adventofcode"
|
||||
version = "1.0.0"
|
||||
|
||||
[project.scripts]
|
||||
aoc = "adventofcode.aoc:main"
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["."]
|
||||
|
||||
Reference in new issue
Block a user