diff --git a/.gitignore b/.gitignore index 07d1e4e..0cca342 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ __pycache__ data/ +inputs/ +solutions/ */input_data.py .env codingquest/2022/input/ diff --git a/pylib/aoc.py b/pylib/aoc.py index 63bfa9f..0a98eb4 100644 --- a/pylib/aoc.py +++ b/pylib/aoc.py @@ -695,17 +695,31 @@ def site(self) -> site.Website: @property def data_file(self) -> pathlib.Path: """Return the path to today's data file.""" - return (self.data_dir / f'{self.day:02d}').with_suffix('.txt') + return (self.data_dir / f'{self.year}.{self.day:02d}.txt') @property def data_dir(self) -> pathlib.Path: - """Return the directory named "data" with the inputs.""" + """Return the directory named "inputs" with the inputs.""" for p in pathlib.Path(__file__).parents: - d = p / 'data' + d = p / 'inputs' if d.exists(): return d raise RuntimeError('No data dir found') + @property + def solutions_file(self) -> pathlib.Path: + """Return the path to today's data file.""" + return (self.solutions_dir / f'{self.year}.txt') + + @property + def solutions_dir(self) -> pathlib.Path: + """Return the directory named "solutions" with the solutions.""" + for p in pathlib.Path(__file__).parents: + d = p / 'solutions' + if d.exists(): + return d + raise RuntimeError('No solution dir found') + @property def day(self) -> int: """Return the day of this class.""" @@ -830,7 +844,7 @@ def solve(self, input_file: Optional[str]) -> None: def check(self, input_file: Optional[str] = None) -> None: """Check the generated solutions match the contents of solutions.txt.""" - lines = (self.data_dir.parent / 'solutions').with_suffix('.txt').read_text().strip().split('\n') + lines = self.solutions_file.read_text().strip().split('\n') solution = None for line in lines: parts = line.split() diff --git a/runner.py b/runner.py index c3ccb41..2524d81 100755 --- a/runner.py +++ b/runner.py @@ -101,15 +101,27 @@ def build(klass, year: Optional[int], day: Optional[int], watch: bool, timeout: @property def base(self): - return pathlib.Path(__file__).parent / str(self.year) + return pathlib.Path(__file__).parent + + @property + def year_path(self) -> pathlib.Path: + return self.base / f"{self.year}" + + @property + def code_path(self) -> pathlib.Path: + return self.year_path / f"d{day:02}.py" + + @property + def solution_path(self) -> pathlib.Path: + return self.base / f"solutions/{self.year}.txt" def from_template(self, day: int) -> None: """Create a new exercise file from template.""" - filename = self.base / f"d{day:02}.py" + filename = self.code_path if filename.exists(): print(f"{filename.name} already exists") return - template_file = self.base / "../shared/tmpl.py" + template_file = self.base / "shared/tmpl.py" template = string.Template(template_file.read_text()) website = site.Website(self.year, day) out = template.substitute( @@ -117,7 +129,6 @@ def from_template(self, day: int) -> None: sample=website.codeblocks(), title=website.title().strip("- "), ) - filename = self.base / f"d{day:02}.py" filename.write_text(out) filename.chmod(0o700) @@ -127,7 +138,7 @@ def december(self, timeout: int) -> None: start = datetime.datetime(year, 11, 30, tzinfo=EST) end = datetime.datetime(year, 12, 25, 1, tzinfo=EST) while start < self.now() < end: - solved = [int(line.split()[0]) for line in (self.base / "solutions.txt").read_text().splitlines()] + solved = [int(line.split()[0]) for line in self.solution_path.read_text().splitlines()] if self.now().day in solved: print("Wait for tomorrow's problem to start and solve it.") self.wait_solve(timeout) @@ -188,7 +199,7 @@ def live_solve(self) -> None: else: # Watch the file. inotify = inotify_simple.INotify() - inotify.add_watch(self.base, inotify_simple.flags.CLOSE_WRITE) + inotify.add_watch(self.year_path, inotify_simple.flags.CLOSE_WRITE) while events := inotify.read(): if not any(i.name == f"d{day:02}.py" for i in events): continue @@ -251,7 +262,7 @@ def live_solve(self) -> None: if not solutions: solutions = {part: obj.run_solver(part, raw_data) for part in (1, 2)} inotify = inotify_simple.INotify() - inotify.add_watch(self.base, inotify_simple.flags.CLOSE_WRITE) + inotify.add_watch(self.year_path, inotify_simple.flags.CLOSE_WRITE) stop_at = self.now() + datetime.timedelta(hours=6) while self.now() < stop_at: @@ -273,7 +284,7 @@ def live_solve(self) -> None: def read_solutions(self) -> dict[int, dict[int, int | str]]: """Return solutions from file.""" solutions: dict[int, dict[int, int | str]] = {} - for line in (self.base / "solutions.txt").read_text().splitlines(): + for line in self.solution_path.read_text().splitlines(): if not line: continue parts = line.split() @@ -319,8 +330,7 @@ def update_solutions(self, day: int, solutions: Optional[dict[int, int | str]] = for line_day in sorted(existing) ] - solution_file = self.base / "solutions.txt" - solution_file.write_text("\n".join(lines) + "\n") + self.solution_path.write_text("\n".join(lines) + "\n") @click.command()