upgrade run.py with click and complete 31829.py
This commit is contained in:
31
init_make.py
31
init_make.py
@@ -1,31 +0,0 @@
|
|||||||
import sys
|
|
||||||
import os
|
|
||||||
import glob
|
|
||||||
|
|
||||||
TC_TARGET_DIR = "_testcases"
|
|
||||||
|
|
||||||
DEFAULT_COUNT = 1
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
count = DEFAULT_COUNT
|
|
||||||
match len(sys.argv):
|
|
||||||
case 1:
|
|
||||||
pass
|
|
||||||
case 2 if sys.argv[1].isdigit() and int(sys.argv[1]) > 0:
|
|
||||||
count = int(sys.argv[1])
|
|
||||||
case _:
|
|
||||||
print("Invalid arguments.")
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
# default make
|
|
||||||
if not os.path.exists("./" + TC_TARGET_DIR):
|
|
||||||
os.mkdir(TC_TARGET_DIR)
|
|
||||||
|
|
||||||
for i in range(1, count + 1):
|
|
||||||
default_in_path = "./" + TC_TARGET_DIR + f"/{i}.in"
|
|
||||||
default_out_path = "./" + TC_TARGET_DIR + f"/{i}.out"
|
|
||||||
with open(default_in_path, "w", encoding="utf-8") as _:
|
|
||||||
pass
|
|
||||||
|
|
||||||
with open(default_out_path, "w", encoding="utf-8") as _:
|
|
||||||
pass
|
|
||||||
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
click>=8.1
|
||||||
192
run.py
192
run.py
@@ -6,6 +6,8 @@ from dataclasses import dataclass
|
|||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
TC_TARGET_DIR = "./_testcases"
|
TC_TARGET_DIR = "./_testcases"
|
||||||
|
|
||||||
|
|
||||||
@@ -15,6 +17,7 @@ class ProblemRunType:
|
|||||||
dir: str
|
dir: str
|
||||||
runner: str
|
runner: str
|
||||||
prefix: str
|
prefix: str
|
||||||
|
prerunner: str = ""
|
||||||
|
|
||||||
|
|
||||||
class ProblemRunEnum:
|
class ProblemRunEnum:
|
||||||
@@ -27,24 +30,29 @@ class ProblemRunEnum:
|
|||||||
zeta_C: ProblemRunType = ProblemRunType(
|
zeta_C: ProblemRunType = ProblemRunType(
|
||||||
name="zeta_C",
|
name="zeta_C",
|
||||||
dir="./zeta_C",
|
dir="./zeta_C",
|
||||||
runner="gcc -std=c11 {source} && a.out",
|
runner="./a.out",
|
||||||
prefix="c",
|
prefix="c",
|
||||||
|
prerunner="gcc -std=c11 {source}",
|
||||||
)
|
)
|
||||||
zeta_cpp: ProblemRunType = ProblemRunType(
|
zeta_cpp: ProblemRunType = ProblemRunType(
|
||||||
name="zeta_cpp",
|
name="zeta_cpp",
|
||||||
dir="./zeta_cpp",
|
dir="./zeta_cpp",
|
||||||
runner="g++ -std=c++17 {source} && ./a.out < {input}",
|
runner="./a.out",
|
||||||
prefix="cpp",
|
prefix="cpp",
|
||||||
|
prerunner="g++ -std=c++17 {source}",
|
||||||
)
|
)
|
||||||
zeta_kotlin: ProblemRunType = ProblemRunType(
|
zeta_kotlin: ProblemRunType = ProblemRunType(
|
||||||
name="zeta_kotlin",
|
name="zeta_kotlin",
|
||||||
dir="./zeta_kotlin",
|
dir="./zeta_kotlin",
|
||||||
runner="kotlinc-jvm {source} -include-runtime -d a.jar && java -jar a.jar -Dfile.encoding=UTF-8 < {input}",
|
runner="java -jar a.jar -Dfile.encoding=UTF-8 < {input}",
|
||||||
prefix="kt",
|
prefix="kt",
|
||||||
|
prerunner="kotlinc-jvm {source} -include-runtime -d a.jar",
|
||||||
)
|
)
|
||||||
|
# WIP
|
||||||
zeta_lua: ProblemRunType = ProblemRunType(
|
zeta_lua: ProblemRunType = ProblemRunType(
|
||||||
name="zeta_lua", dir="./zeta_lua", runner="", prefix="lua"
|
name="zeta_lua", dir="./zeta_lua", runner="", prefix="lua"
|
||||||
)
|
)
|
||||||
|
# ExceptionType
|
||||||
err: ProblemRunType = ProblemRunType(name="err", dir="", runner="", prefix="")
|
err: ProblemRunType = ProblemRunType(name="err", dir="", runner="", prefix="")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -64,102 +72,126 @@ class ProblemRunEnum:
|
|||||||
return ProblemRunEnum.err
|
return ProblemRunEnum.err
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
@click.group()
|
||||||
rtype: ProblemRunType
|
def cli():
|
||||||
problem_code: int
|
pass
|
||||||
cnt: int
|
|
||||||
verbose_flag: bool = False
|
|
||||||
match len(sys.argv):
|
|
||||||
case 3:
|
|
||||||
rtype = ProblemRunEnum.quicklink(sys.argv[1])
|
|
||||||
problem_code = sys.argv[2] if sys.argv[2].isdigit() else None
|
|
||||||
cnt = 1
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
rtype = ProblemRunEnum.quicklink(sys.argv[1])
|
|
||||||
problem_code = int(sys.argv[2]) if sys.argv[2].isdigit() else None
|
|
||||||
if sys.argv[3] == "--verbose":
|
|
||||||
verbose_flag = True
|
|
||||||
cnt = 1
|
|
||||||
else:
|
|
||||||
cnt = (
|
|
||||||
int(sys.argv[3])
|
|
||||||
if sys.argv[3].isdigit() and int(sys.argv[3]) > 0
|
|
||||||
else 1
|
|
||||||
)
|
|
||||||
case 5:
|
|
||||||
rtype = ProblemRunEnum.quicklink(sys.argv[1])
|
|
||||||
problem_code = int(sys.argv[2]) if sys.argv[2].isdigit() else None
|
|
||||||
|
|
||||||
cnt = (
|
@click.command()
|
||||||
int(sys.argv[3])
|
@click.argument("runtype_string", type=str, nargs=1, required=True)
|
||||||
if sys.argv[3].isdigit() and int(sys.argv[3]) > 0
|
@click.argument("problem_code", type=str, nargs=1, required=True)
|
||||||
else 1
|
@click.argument("count", type=int, nargs=1, required=False, default=1)
|
||||||
)
|
@click.option("--verbose", "-v", is_flag=True)
|
||||||
|
@click.option("--profile", "-p", is_flag=True)
|
||||||
|
def run(
|
||||||
|
runtype_string: str, problem_code: str, count: int, verbose: bool, profile: bool
|
||||||
|
):
|
||||||
|
runtype: ProblemRunType = ProblemRunEnum.quicklink(runtype_string)
|
||||||
|
if runtype is ProblemRunEnum.err:
|
||||||
|
raise click.UsageError("Error RUNTYPE.")
|
||||||
|
|
||||||
if sys.argv[4] == "--verbose":
|
if count < 1:
|
||||||
verbose_flag = True
|
raise click.UsageError("COUNT must be greater than 1.")
|
||||||
else:
|
|
||||||
pass
|
|
||||||
case _:
|
|
||||||
print("Invalid argument count.")
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
if rtype is ProblemRunEnum.err:
|
problem_code_path = f"{runtype.dir}/{problem_code}.{runtype.prefix}"
|
||||||
print(f"Invalid run type: `{sys.argv[1]}`.")
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
problem_code_path = f"{rtype.dir}/{problem_code}.{rtype.prefix}"
|
|
||||||
if not os.path.exists(problem_code_path):
|
if not os.path.exists(problem_code_path):
|
||||||
print(f"Invalid problem code: `{problem_code}`")
|
raise click.UsageError("Problem does not exist.")
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
io_files: list[str] = [
|
tc_files: list[str] = [
|
||||||
fpath
|
fpath
|
||||||
for fpath in os.listdir(TC_TARGET_DIR)
|
for fpath in os.listdir(TC_TARGET_DIR)
|
||||||
if os.path.isfile(os.path.join(TC_TARGET_DIR, fpath))
|
if os.path.isfile(os.path.join(TC_TARGET_DIR, fpath))
|
||||||
]
|
]
|
||||||
|
|
||||||
for c in range(1, cnt + 1):
|
for c in range(1, count + 1):
|
||||||
inputs = None
|
inpf = None
|
||||||
outputs = []
|
outputfs = []
|
||||||
for name in io_files:
|
for name in tc_files:
|
||||||
ix = re.match(f"{c}.in", name)
|
ix = re.match(f"{c}.in", name)
|
||||||
ox = re.match(f"{c}.out[0-9]*", name)
|
ox = re.match(f"{c}.out[0-9]*", name)
|
||||||
if ix:
|
if ix:
|
||||||
inputs = name
|
inpf = name
|
||||||
elif ox:
|
elif ox:
|
||||||
outputs.append(name)
|
outputfs.append(name)
|
||||||
if (not inputs) or (not outputs):
|
|
||||||
print(f"{c:02d}: Pass")
|
if (not inpf) or (not outputfs):
|
||||||
|
click.echo(f"{c:02d}: {None}")
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
with open(os.path.join(TC_TARGET_DIR, inputs), 'r', encoding='utf-8') as inputf:
|
# check
|
||||||
stdout = subprocess.run(
|
with open(os.path.join(TC_TARGET_DIR, inpf), "r", encoding="utf-8") as f:
|
||||||
rtype.runner.format(
|
if runtype.prerunner:
|
||||||
source=problem_code_path, input= os.path.join(TC_TARGET_DIR, inputs)
|
try:
|
||||||
).split(),
|
_ = subprocess.run(
|
||||||
check=True,
|
runtype.prerunner.format(
|
||||||
capture_output=True,
|
source=problem_code_path,
|
||||||
text=True,
|
).split(),
|
||||||
stdin = inputf
|
check=True,
|
||||||
).stdout
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
click.echo(">>>>>> [Error while PRERUNNER process] >>>>>>")
|
||||||
|
click.echo(f"{e.stderr}")
|
||||||
|
click.echo(">>>>>> [Error while PRERUNNER process] >>>>>>")
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
stdout = subprocess.run(
|
||||||
|
runtype.runner.format(
|
||||||
|
source=problem_code_path,
|
||||||
|
).split(),
|
||||||
|
check=True,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
stdin=f,
|
||||||
|
).stdout
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
click.echo(">>>>>> [Error while RUNNER process] >>>>>>")
|
||||||
|
click.echo(f"{e.stderr}")
|
||||||
|
click.echo(f"returncode: {e.returncode}")
|
||||||
|
click.echo(">>>>>> [Error while RUNNER process] >>>>>>")
|
||||||
|
stdout = ""
|
||||||
|
continue
|
||||||
|
|
||||||
flag = False
|
flag = False
|
||||||
for outputpath in outputs:
|
for outputpath in outputfs:
|
||||||
with open(
|
with open(
|
||||||
os.path.join(TC_TARGET_DIR, outputpath), "r", encoding="utf-8"
|
os.path.join(TC_TARGET_DIR, outputpath), "r", encoding="utf-8"
|
||||||
) as f:
|
) as f:
|
||||||
if stdout.strip() == f.read().strip():
|
if stdout.strip() == f.read().strip():
|
||||||
flag = True
|
flag = True
|
||||||
break
|
break
|
||||||
|
|
||||||
print(f"{c:02d}: {flag}")
|
click.echo(f"{c:02d}: {flag}")
|
||||||
if verbose_flag:
|
if verbose:
|
||||||
print("===")
|
click.echo("===" * 3)
|
||||||
print(stdout)
|
click.echo(stdout)
|
||||||
print("===")
|
click.echo("===" * 3)
|
||||||
|
|
||||||
|
|
||||||
### TODO: --profile argument 추가를 위한 command dispatcher 개선
|
@click.command(name="init")
|
||||||
### TODO: WIP
|
@click.argument("count", type=int)
|
||||||
|
def init(count: int):
|
||||||
|
if count < 1:
|
||||||
|
raise click.UsageError("COUNT must be greater than 1.")
|
||||||
|
else:
|
||||||
|
if not os.path.exists("./" + TC_TARGET_DIR):
|
||||||
|
os.mkdir(TC_TARGET_DIR)
|
||||||
|
for i in range(1, count + 1):
|
||||||
|
default_in_path = "./" + TC_TARGET_DIR + f"/{i}.in"
|
||||||
|
default_out_path = "./" + TC_TARGET_DIR + f"/{i}.out"
|
||||||
|
with open(default_in_path, "w", encoding="utf-8") as _:
|
||||||
|
pass
|
||||||
|
|
||||||
|
with open(default_out_path, "w", encoding="utf-8") as _:
|
||||||
|
pass
|
||||||
|
|
||||||
|
click.echo("Testcases was made successfully!")
|
||||||
|
|
||||||
|
|
||||||
|
cli.add_command(run)
|
||||||
|
cli.add_command(init)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
cli()
|
||||||
|
|||||||
51
zeta_python/completed/31829.py
Normal file
51
zeta_python/completed/31829.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import sys
|
||||||
|
import heapq
|
||||||
|
|
||||||
|
input = sys.stdin.readline
|
||||||
|
|
||||||
|
|
||||||
|
def solve(N, K, X, Y, E_X, E_Y):
|
||||||
|
G_X = [[] for _ in range(N + 1)]
|
||||||
|
G_Y = [[] for _ in range(N + 1)]
|
||||||
|
for s, e, d in E_X:
|
||||||
|
G_X[s].append((e, d))
|
||||||
|
G_X[e].append((s, d))
|
||||||
|
|
||||||
|
for s, e, d in E_Y:
|
||||||
|
G_Y[s].append((e, d))
|
||||||
|
G_Y[e].append((s, d))
|
||||||
|
|
||||||
|
dist = [float("inf") for _ in range(N + 1)]
|
||||||
|
dist[1] = 0
|
||||||
|
|
||||||
|
pq = []
|
||||||
|
heapq.heappush(pq, (dist[1], 1))
|
||||||
|
|
||||||
|
while pq:
|
||||||
|
now_dist, now_pos = heapq.heappop(pq)
|
||||||
|
if dist[now_pos] < now_dist:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for target, cost in G_X[now_pos]:
|
||||||
|
new_cost = now_dist + cost
|
||||||
|
if new_cost < dist[target]:
|
||||||
|
dist[target] = new_cost
|
||||||
|
heapq.heappush(pq, (new_cost, target))
|
||||||
|
|
||||||
|
for target, cost in G_Y[now_pos]:
|
||||||
|
if now_dist < K:
|
||||||
|
new_cost = K + cost
|
||||||
|
else:
|
||||||
|
new_cost = now_dist + cost
|
||||||
|
|
||||||
|
if new_cost < dist[target]:
|
||||||
|
dist[target] = new_cost
|
||||||
|
heapq.heappush(pq, (new_cost, target))
|
||||||
|
return dist[N]
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
N, K, X, Y = map(int, input().split())
|
||||||
|
E_X = list(map(int, input().split()) for _ in range(X))
|
||||||
|
E_Y = list(map(int, input().split()) for _ in range(Y))
|
||||||
|
print(solve(N, K, X, Y, E_X, E_Y))
|
||||||
Reference in New Issue
Block a user