专业竞争输入自动生成器和面向对象的故事


概述

  • 随机自动为竞赛专业人士生成输入测试用例
  • 介绍如何实现并看到面向对象的好处

不仅是那些想要使用自动生成功能的人,而且还有那些想知道比竞争专业人士更进一步的编程的人,
我认为学习面向对象编程的人可以阅读此内容。
完整的源代码可以在这里找到。

您可以做什么:自动生成输入测试用例

如果准备了这样的输入宏→

1
2
3
4
Int(N,2,5)
Float(a,1,100,5) Perm(1,N+4)
Str([a-z]{3,2*N})
*N(2)

输入将显示→

1
2
3
4
5
6
7
8
9
10
output:
4
54.81887 3 2 4 7 1 8 5 6
yyl
4.32497 4 1 6 5 3 8 7 2
yziuqiac
42.84603 3 2 4 7 8 6 5 1
vsjajs
65.07176 7 5 8 3 4 6 1 2
rbq

其他

加权图:

1
2
Int(N,3,5) Int(M,N-1,N*(N-1)//2)
Graph1(N,M,0,1000)

1
2
3
4
5
6
7
output:
4 5
1 2 392
1 3 328
1 4 891
2 3 264
3 4 227

字符串:

1
2
3
Int(N,4,6) Int(M,4,6)
Str([.#]{M})
*N(1)

1
2
3
4
5
6
output:
4 5
###.#
#.#.#
#..##
.###.

如果您对

函数本身感兴趣,可以在此处找到列表。

*到目前为止,由于我们刚刚定义了内部类,因此,如果您想一次生成大量测试用例或将其写入文件,则需要使用此类对Python进行编码。

实现方法

它具有面向对象的实现。
大致上,

  • 负责读取整个宏的类(LineCollection)
  • 负责逐行读取宏的类(行)
  • 一行宏中负责空间定界符的类(Item及其子类)
  • 它分为

    。这是我管理i 1并抛出必要工作(i = 1,2)的图像。
    所有类都有以下共同的方法:

  • from_str():解析输入的宏字符串并初始化该类。

  • generate():为其管理的范围生成一个随机输入测试用例。

  • 总之,它看起来像下表:

    <表格>

    线路集合

    项目


    <身体>

    from_str()

    加载整个宏

    读一行

    读一个字

    生成()

    整个宏的输出生成

    一行输出的输出

    生成一个单词的输出


    重点是

    • 要使用整体,LineCollection.from_str(输入宏)→generate()
    • 如果要增加新的宏类型的数量,只需定义具有上述三种方法的Item类的子类即可(无需更改Line或LineCollection)。

    是类似

    的东西吗?

    源代码

    具体来说,我将检查源代码。

    LineCollection

    <表格>

    LineCollection

    项目


    <身体>

    from_str()

    加载整个宏

    读一行

    读一个字

    生成()

    整个宏的输出生成

    一行输出的输出

    生成一个单词的输出


    self.ls具有宏的每一行的行列表。
    支持" * N(1)"之类的宏有点复杂,但是我们要做的是

    • from_str()=加载整个宏:初始化与每一行相对应的Line并将其放入self.ls
    • generate()=为整个宏生成输出:为self.ls中的每一行生成输出,并以换行符返回

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    class LineCollection:
        def __init__(self, ls, s=None):
            """ls: list of Line
            """
            self.ls = ls
            self.s = s
        @classmethod
        def from_str(cls, s):
            lines = s.split("\n")
            i = 0
            ls = []
            for i in range(len(lines)):
                if lines[i].startswith("*"):
                    name, num = lines[i][1:].split("(",1)
                    num = int(num[:-1])
                    ls.append((name, num))
                else:
                    l = Line.from_str(lines[i])
                    ls.append(l)
            return cls(ls, s)
        def generate(self):
            i = 0
            prv = 0
            output = []
            while i<len(self.ls):
                while i<len(self.ls) and not isinstance(self.ls[i], tuple):
                    i += 1
                if i<len(self.ls) and isinstance(self.ls[i], tuple):
                    m, num = self.ls[i]
                    i += 1
                else:
                    m = 0
                    num = 0
                for j in range(prv, i-num-1):
                    if isinstance(self.ls[j], tuple):
                        continue
                    output.append(self.ls[j].generate())
                if num!=0:
                    try:
                        m = Item.names[m]
                    except KeyError:
                        raise ValueError("テストケース数が未定義: 上何行見るかの指定が間違っていません?")
                    for _ in range(m):
                        for j in range(i-num-1, i-1):
                            if isinstance(self.ls[j], tuple):
                                continue
                            output.append(self.ls[j].generate())
                prv = i
            return "\n".join(output)

    Line

    <表格>

    线路集合

    线

    项目


    <身体>

    from_str()

    加载整个宏

    读一行

    读一个字

    生成()

    整个宏的输出生成

    输出一行的输出

    生成一个单词的输出


    self.l管理您要查看的行中存在的项目列表。
    类似于Line Collection,

    • from_str():用空格分隔一行的读取,读取每个类的类名和参数,初始化Item,然后将其放到self.l中。
    • generate():让self.l中的每个Item生成输出并以空格返回结果