Python对拍器
对拍器对蓝桥杯这种赛制的比赛还是比较有用的
以 AcWing4782.第k个数 为例
对拍器主代码main.py
import os
from random import randint, uniform
import subprocess
T = 10 # 样例组数
# 生成随机数据的函数
def generate_date():
A = [0] * 1010
for t in range(1, T + 1):
# 数据的文件名
filename = f"in_{t}.txt"
with open(filename, "w") as file:
n = randint(1, 1000)
k = randint(1, n)
file.write(str(n)+ " " + str(k) + "\n")
for i in range(n):
A[i] = randint(0, 100)
nums = " ".join(map(str, A[:n]))
file.write(nums + "\n")
print(f'generate_ok:......{T}')
# 调用py程序函数
def run(process_name):
for t in range(1, T + 1):
# 文件名
out_filename = f"{process_name}_out_{t}.txt"
in_filename = f"in_{t}.txt"
subprocess.run(['python', f'{process_name}.py'],
stdin = open(in_filename, "r"),
stdout = open(out_filename, "w"))
print(f'run_{process_name}_ok:......{T}')
# 对比txt文件是否相同的函数
def diff(file1, file2):
for t in range(1, T + 1):
f1 = f"{file1}_out_{t}.txt"
f2 = f"{file2}_out_{t}.txt"
with open(f1, "r") as s, open(f2, "r") as ss:
lines1 = s.readlines()
lines2 = ss.readlines()
if len(lines1) != len(lines2):
print(f'{t}:lines error')
continue
ok = 1
for line1,line2 in zip(lines1, lines2):
if line1 != line2:
print(f'{t}:exist error')
ok = 0
break
if ok: print(f'{t}:ok')
if __name__ == "__main__":
# 生成输入文件
generate_date()
# 调用正解
file_true = "True"
run(file_true)
# 调用测试程序
file_my = "A"
run(file_my)
# 调用对比程序
diff(file_true, file_my)
generate_date函数
其中样例组数T为全局变量
输出文件命名根据样例的组数来进行编号
具体的输出内容需要根据题目信息来确定,考虑暴力解法的时间复杂度,测试样例的范围不宜过大
random库的一些常用函数:
- randint(a, b):产生[a, b]之间的随机整数,b也可以取到
- randrange(a):产生[0, a)之间的随机整数,不包括b
- random():产生[0.0, 1.0)之间的随机浮点数
- uniform(a, b):产生[a, b]之间的随机浮点数
- choice(seq):从目标序列类型中随机返回一个元素
- shuffle(seq):将序列类型中元素随机排列,返回打乱后的序列
def generate_date():
A = [0] * 1010
for t in range(1, T + 1):
# 数据的文件名
filename = f"in_{t}.txt"
with open(filename, "w") as file:
n = randint(1, 1000)
k = randint(1, n)
file.write(str(n)+ " " + str(k) + "\n")
for i in range(n):
A[i] = randint(0, 100)
nums = " ".join(map(str, A[:n]))
file.write(nums + "\n")
print(f'generate_ok:......{T}')
run函数
接受一个参数:调用py程序的名称,这个名称需要在main函数中指定,分别是暴力解法的文件名以及测试解法的文件名
输出文件命名包括py程序的名称以及样例组数的编号
用subprocess.run()
方法调用py文件进行执行,指定输入输出路径
subprocess在标准库内,可以放心使用
def run(process_name):
for t in range(1, T + 1):
# 文件名
out_filename = f"{process_name}_out_{t}.txt"
in_filename = f"in_{t}.txt"
subprocess.run(['python', f'{process_name}.py'],
stdin = open(in_filename, "r"),
stdout = open(out_filename, "w"))
print(f'run_{process_name}_ok:......{T}')
diff函数
这个函数比较简单,接受两个参数:分别是暴力解法的文件名和测试解法的文件名
需要根据run函数中的输出文件名的命名规则,对输出文件进行遍历
输出文件存在差异即报告错误即可
def diff(file1, file2):
for t in range(1, T + 1):
f1 = f"{file1}_out_{t}.txt"
f2 = f"{file2}_out_{t}.txt"
with open(f1, "r") as s, open(f2, "r") as ss:
lines1 = s.readlines()
lines2 = ss.readlines()
if len(lines1) != len(lines2):
print(f'{t}:lines error')
continue
ok = 1
for line1,line2 in zip(lines1, lines2):
if line1 != line2:
print(f'{t}:exist error')
ok = 0
break
if ok: print(f'{t}:ok')
True.py(赛时为暴力解法)
n,k = map(int, input().split())
A = list(map(int, input().split()))
A.sort(reverse = True)
print(A[k-1])
A.py(赛时为待验证的解法)
这里只是为了测试对拍器程序的正确性而构造的代码
n,k = map(int, input().split())
A = list(map(int, input().split()))
A.sort(reverse = True)
if n & 1: print(A[k - 1])
else: print(A[k - 10])
运行结果
保证main.py
、True.py
、A.py
三个文件在同一文件夹下即可
最后生成的测试样例、输出结果也会在同一文件目录下
运行main.py
后文件目录如下:
测试结果输出
测试结果所有的n为奇数的测试样例显示通过,n为偶数的测试样例样例显示错误
这样就可以去打开对应的测试样例来看具体错误样例