CCC 42 level 1
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from solution import process_inputs, solve
|
||||
|
||||
|
||||
USAGE = """\
|
||||
usage: python main.py [--tests=DIR] [--output=DIR] <command> [args]
|
||||
|
||||
commands:
|
||||
single path/to/test.in run a single test file
|
||||
range START [END] run tests START..END (inclusive)
|
||||
|
||||
flags:
|
||||
--tests=DIR directory containing test inputs (default: tests)
|
||||
--output=DIR directory for outputs (default: output)
|
||||
"""
|
||||
|
||||
|
||||
config = {
|
||||
"input_name": re.compile(r"in_level-[0-9]_([0-9])-(?:small|large)\.txt"),
|
||||
"tests_dir": Path("tests"),
|
||||
"output_dir": Path("output")
|
||||
}
|
||||
|
||||
class FillingList(list):
|
||||
def __init__(self, iterable=(), fill=None):
|
||||
super().__init__(iterable)
|
||||
self.fill = fill
|
||||
|
||||
def __setitem__(self, index, value):
|
||||
if isinstance(index, int) and index >= len(self):
|
||||
self.extend([self.fill] * (index - len(self) + 1))
|
||||
super().__setitem__(index, value)
|
||||
|
||||
|
||||
|
||||
def run_single_test(input_path: str, output_path: str):
|
||||
print(f"Input path: {input_path}")
|
||||
print(f"Output path: {output_path}")
|
||||
|
||||
with open(input_path, 'r') as f:
|
||||
data = f.read()
|
||||
|
||||
testcases = process_inputs(data)
|
||||
solution = solve(testcases)
|
||||
|
||||
with open(output_path, 'w') as f:
|
||||
f.write(solution)
|
||||
|
||||
|
||||
|
||||
def run_test_range(start_test: int, end_test: int | None = None):
|
||||
print(f"Running test range {start_test} {end_test}")
|
||||
input_files = FillingList()
|
||||
# Find all input files
|
||||
for filename in os.listdir(config['tests_dir']):
|
||||
path = os.path.join(config['tests_dir'], filename)
|
||||
if not os.path.isfile(path):
|
||||
continue
|
||||
m = config['input_name'].fullmatch(filename)
|
||||
if m:
|
||||
input_files[int(m.group(1))] = {
|
||||
"path": path,
|
||||
"filename": filename,
|
||||
}
|
||||
else:
|
||||
print(f"{filename} does not match, skipping")
|
||||
|
||||
if not end_test:
|
||||
end_test = len(input_files)
|
||||
|
||||
# Run solution for each discovered input file
|
||||
for i, input_file in enumerate(input_files[start_test:(end_test + 1)]):
|
||||
if not input_file:
|
||||
print(f'WARNING: Could not find test #{i}')
|
||||
print(f'running test {i} looking at path {input_file['path']}')
|
||||
|
||||
output_name = input_file['filename'].replace('in', 'out')
|
||||
output_path = config['output_dir'] / output_name
|
||||
|
||||
run_single_test(input_file['path'], output_path)
|
||||
|
||||
|
||||
|
||||
def parse_argv(argv):
|
||||
"""Split argv into ({flag: value}, [positional]). Supports --k=v and --k v."""
|
||||
flags, positional = {}, []
|
||||
i = 0
|
||||
while i < len(argv):
|
||||
arg = argv[i]
|
||||
if arg.startswith("--"):
|
||||
if "=" in arg:
|
||||
key, value = arg[2:].split("=", 1)
|
||||
else:
|
||||
key = arg[2:]
|
||||
i += 1
|
||||
if i >= len(argv):
|
||||
raise SystemExit(f"error: flag --{key} requires a value\n\n{USAGE}")
|
||||
value = argv[i]
|
||||
flags[key] = value
|
||||
else:
|
||||
positional.append(arg)
|
||||
i += 1
|
||||
return flags, positional
|
||||
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
argv = sys.argv[1:] if argv is None else argv
|
||||
flags, positional = parse_argv(argv)
|
||||
|
||||
unknown = set(flags) - {"tests", "output"}
|
||||
if unknown:
|
||||
raise SystemExit(f"error: unknown flag(s): {', '.join(sorted(unknown))}\n\n{USAGE}")
|
||||
|
||||
config["tests_dir"] = Path(flags.get("tests", config["tests_dir"]))
|
||||
config["output_dir"] = Path(flags.get("output", config["output_dir"]))
|
||||
os.makedirs(config["output_dir"], exist_ok=True)
|
||||
|
||||
if not positional:
|
||||
raise SystemExit(USAGE)
|
||||
|
||||
command, *args = positional
|
||||
|
||||
if command == "single":
|
||||
if len(args) != 1:
|
||||
raise SystemExit(f"error: 'single' takes exactly one path\n\n{USAGE}")
|
||||
input_path = Path(args[0])
|
||||
if not input_path.is_file():
|
||||
raise SystemExit(f"error: no such file: {input_path}")
|
||||
output_path = Path(config["output_dir"]) / input_path.with_suffix(".out").name
|
||||
run_single_test(str(input_path), str(output_path))
|
||||
|
||||
elif command == "range":
|
||||
if len(args) not in (1, 2):
|
||||
raise SystemExit(f"error: 'range' takes START [END]\n\n{USAGE}")
|
||||
try:
|
||||
start_test = int(args[0])
|
||||
end_test = int(args[1]) if len(args) == 2 else None
|
||||
except ValueError:
|
||||
raise SystemExit(f"error: range bounds must be integers\n\n{USAGE}")
|
||||
run_test_range(start_test, end_test)
|
||||
|
||||
else:
|
||||
raise SystemExit(f"error: unknown command {command!r}\n\n{USAGE}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
|
||||
|
||||
# Path: solution.py
|
||||
# def process_inputs(inputs):
|
||||
# lines = inputs.split('\n')
|
||||
# lines = iter(lines)
|
||||
|
||||
# testcases_num = int(next(lines))
|
||||
# testcases = []
|
||||
|
||||
# for i in range(testcases_num):
|
||||
# line = next(lines)
|
||||
|
||||
# testcase = {}
|
||||
|
||||
# return [{'testcase': 'testcase1'}]
|
||||
|
||||
|
||||
|
||||
|
||||
# def solve(testcases):
|
||||
# res = ''
|
||||
# for i, testcase in enumerate(testcases):
|
||||
# print('Solving testcase #', i + 1)
|
||||
# res += process_testcase(**testcase) + '\n'
|
||||
|
||||
# return res
|
||||
|
||||
|
||||
|
||||
# def process_testcase(arg1, args):
|
||||
# return 'solution'
|
||||
Reference in New Issue
Block a user