Added input arg to solver.
parent
f5a99b876d
commit
554ea25596
|
@ -1,5 +1,6 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import importlib
|
import importlib
|
||||||
import __main__
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import pathlib
|
import pathlib
|
||||||
|
@ -8,7 +9,7 @@ import traceback
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
|
|
||||||
PATH = pathlib.Path(__file__).parent
|
PATH = pathlib.Path(__file__).parent
|
||||||
INPUT_PATH = PATH / "input"
|
INPUT_PATH = PATH / 'input'
|
||||||
|
|
||||||
class Tests(list):
|
class Tests(list):
|
||||||
"""
|
"""
|
||||||
|
@ -58,22 +59,9 @@ class Solver:
|
||||||
self.partI = getattr(mod, 'partI')
|
self.partI = getattr(mod, 'partI')
|
||||||
self.partII = getattr(mod, 'partII')
|
self.partII = getattr(mod, 'partII')
|
||||||
|
|
||||||
def format_result(f):
|
|
||||||
"""
|
|
||||||
Formatting decorator. Formats and prints a tuple representing
|
|
||||||
the results of partI and partII.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def aux(*args):
|
|
||||||
solver = args[0]
|
|
||||||
ptI, ptII = f(*args)
|
|
||||||
print("Part One : {}".format(ptI))
|
|
||||||
print("Part Two : {}".format(ptII))
|
|
||||||
return aux
|
|
||||||
|
|
||||||
@format_result
|
|
||||||
def solve(self, puzzle_input):
|
def solve(self, puzzle_input):
|
||||||
"""Solves puzzle input and prints the results."""
|
"""Solves puzzle input and returns pair of solutions"""
|
||||||
puzzle_input = puzzle_input.rstrip()
|
puzzle_input = puzzle_input.rstrip()
|
||||||
if self.preproc != NotImplemented:
|
if self.preproc != NotImplemented:
|
||||||
puzzle_input = self.preproc(puzzle_input)
|
puzzle_input = self.preproc(puzzle_input)
|
||||||
|
@ -81,9 +69,8 @@ class Solver:
|
||||||
ptII = self.partII(puzzle_input)
|
ptII = self.partII(puzzle_input)
|
||||||
return ptI, ptII
|
return ptI, ptII
|
||||||
|
|
||||||
@format_result
|
|
||||||
def test(self):
|
def test(self):
|
||||||
"""Tests the solver and prints the results."""
|
"""Tests the solver and returns pair of test results."""
|
||||||
tests = self.tests
|
tests = self.tests
|
||||||
if self.preproc != NotImplemented:
|
if self.preproc != NotImplemented:
|
||||||
tests = [(self.preproc(str(t)), s1, s2)
|
tests = [(self.preproc(str(t)), s1, s2)
|
||||||
|
@ -94,11 +81,6 @@ class Solver:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def read_input(mod_name):
|
|
||||||
"""Reads input of module with mod_name."""
|
|
||||||
name = mod_name + ".txt"
|
|
||||||
with open(INPUT_PATH / name) as f:
|
|
||||||
r = f.read()
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
|
||||||
|
@ -111,60 +93,97 @@ parser.description = \
|
||||||
parser.add_argument('-d', '--day',
|
parser.add_argument('-d', '--day',
|
||||||
action='store',
|
action='store',
|
||||||
type=str,
|
type=str,
|
||||||
metavar="DAY[-DAY]",
|
metavar='DAY[-DAY]',
|
||||||
help="solve puzzle of day DAY or of range DAY-DAY")
|
help='solve puzzle of day DAY or of range DAY-DAY')
|
||||||
|
|
||||||
|
parser.add_argument('-i', '--input',
|
||||||
|
action='store',
|
||||||
|
type=str,
|
||||||
|
metavar='INPUT',
|
||||||
|
default=INPUT_PATH,
|
||||||
|
help='use INPUT as puzzle input')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
parser.add_argument('-t', '--test',
|
parser.add_argument('-t', '--test',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help="run tests")
|
help="run tests")
|
||||||
|
|
||||||
def parse_day_arg(s):
|
def parse_day_arg(s, mind, maxd):
|
||||||
"""Parses day argument. Returns a list of days."""
|
"""Parses day argument. Returns a list of days."""
|
||||||
split = s.split('-')
|
split = s.split('-')
|
||||||
if len(split) == 1:
|
if len(split) == 1:
|
||||||
return [int(split[0])]
|
return [int(split[0])]
|
||||||
elif len(split) == 2:
|
elif len(split) == 2:
|
||||||
d, D = map(int, split)
|
d, D = map(int, split)
|
||||||
return list(range(d, D+1))
|
return list(range(max(1, d), min(D+1, 26)))
|
||||||
raise ValueError
|
raise ValueError
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
if __name__ == '__main__':
|
|
||||||
solver_pattern = re.compile("day(\d\d?).py")
|
solver_pattern = re.compile("day(\d\d?).py")
|
||||||
matches = map(solver_pattern.fullmatch, os.listdir(PATH))
|
matches = map(solver_pattern.fullmatch, os.listdir(PATH))
|
||||||
solvers = {int(s.group(1)) : s.group(0) for s in matches if s != None}
|
solvers = {int(s.group(1)) : s.group(0) for s in matches if s != None}
|
||||||
|
|
||||||
days = list(range(1, 25+1))
|
mind, maxd = min(solvers), max(solvers)
|
||||||
|
days = sorted(solvers.keys())
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
#Handle day argument
|
||||||
if args.day != None:
|
if args.day != None:
|
||||||
try:
|
try:
|
||||||
days = parse_day_arg(args.day)
|
days = parse_day_arg(args.day, mind, maxd)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("error : invalid format of argument -d/--day")
|
return 'invalid format of argument -d/--day'
|
||||||
quit()
|
|
||||||
|
|
||||||
|
#Handle input argument
|
||||||
|
inputs = {}
|
||||||
|
input_path = pathlib.Path('.')
|
||||||
|
num_pattern = re.compile(r'\d\d?')
|
||||||
|
try:
|
||||||
|
fs = os.listdir(args.input)
|
||||||
|
input_path /= args.input
|
||||||
|
for fn in fs:
|
||||||
|
ns = num_pattern.findall(fn)
|
||||||
|
if ns == []:
|
||||||
|
print('warning : ignoring input file {}'.format(fn))
|
||||||
|
continue
|
||||||
|
n = int(ns[0])
|
||||||
|
inputs[n] = fn
|
||||||
|
except FileNotFoundError:
|
||||||
|
return "input directory or file doesn't exist"
|
||||||
|
except NotADirectoryError:
|
||||||
|
if len(days) > 1:
|
||||||
|
return "input is file"
|
||||||
|
day = days[0]
|
||||||
|
inputs[day] = args.input
|
||||||
|
|
||||||
|
#Solve days
|
||||||
for d in days:
|
for d in days:
|
||||||
print("=" * 6 + " Day {} ".format(d) + "=" * 6)
|
print("=" * 6 + " Day {} ".format(d) + "=" * 6)
|
||||||
if d not in solvers:
|
if d not in solvers:
|
||||||
print("error : no solver for day {}".format(d))
|
return "no solver for day {}".format(d)
|
||||||
continue
|
|
||||||
mod_name = solvers[d][:-3]
|
mod_name = solvers[d][:-3]
|
||||||
try:
|
try:
|
||||||
mod = importlib.import_module(mod_name)
|
mod = importlib.import_module(mod_name)
|
||||||
solver = Solver(mod)
|
solver = Solver(mod)
|
||||||
except:
|
except:
|
||||||
print("error : bad solver")
|
return "bad solver\n\n{}".format(traceback.format_exc())
|
||||||
print(traceback.format_exc())
|
|
||||||
continue
|
|
||||||
try:
|
try:
|
||||||
if args.test:
|
if args.test:
|
||||||
solver.test()
|
ptI, ptII = solver.test()
|
||||||
else:
|
else:
|
||||||
puzzle_input = read_input(mod_name)
|
if d not in inputs:
|
||||||
solver.solve(puzzle_input)
|
return 'no input file'
|
||||||
|
with open(input_path / inputs[d]) as f:
|
||||||
|
puzzle_input = f.read()
|
||||||
|
ptI, ptII = solver.solve(puzzle_input)
|
||||||
|
print("Part One : {}".format(ptI))
|
||||||
|
print("Part Two : {}".format(ptII))
|
||||||
except:
|
except:
|
||||||
print("error : error in solver")
|
return "error in solver\n\n{}".format(traceback.format_exc())
|
||||||
print(traceback.format_exc())
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
error = main()
|
||||||
|
if error != None:
|
||||||
|
print('error : {}'.format(error))
|
||||||
|
|
Loading…
Reference in New Issue