• OJ平台代码模板自动生成



    前言

    经常使用CSDN的小伙伴应该知道, 最近CSDN举办了好几期编程竞赛, 其中的编程模板, 都是有python脚本自动生成的, 这篇文章, 用以记录编程模板自动生成的开发过程.

    我们以 java 语言为例进行讲解.

    一、分析数据

    要想自动化, 首先得发现数据的规律. 分析题库中的题目发现, 可以按照输入类型进行划分, 以下是可能的几个类型:

    1、输入一个整数
    2、输入一个定长的整数数组
    3、输入一个变长的整数数组
    4、输入一个定长的二维数组
    5、输入一个行固定,列可变的二维数组
    6、输入一个列固定,行可变的二位数组
    7、输入多个整数
    ......
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    同样, 对于输出的数据, 也可以按类型划分, 以下是常见的几种可能的类型:

    这里以整数为例

    1、输出一个整数
    2、输出一个整数数组
    3、输出一个二维的整数数组
    ......
    
    • 1
    • 2
    • 3
    • 4

    只要我们时间足够多, 就可以实现全部输入类型

    二、解析输入

    Java技能树的第一道题: A+B 为例
    请添加图片描述

    从输入数据上可以看出,该题属于输入多个整数类型

    我们先来看看, Java 从命令行读取一个整数的代码:

    读取一个整数

    Scanner scan = new Scanner(System.in);
    String str_0 = scan.nextLine().trim();
    int a = Integer.parseInt(str_0);
    
    • 1
    • 2
    • 3

    这是一行一个整数的情况

    读取多行整数

    如果有多行, 每行都只有一个整数, 例如:

    输入:
    1
    2
    3
    
    • 1
    • 2
    • 3
    • 4

    那我们只需要修改下变量名, 多读取几行就行了, 如:

    Scanner scan = new Scanner(System.in);
    
    String str_0 = scan.nextLine().trim();
    int a = Integer.parseInt(str_0);
    
    String str_1 = scan.nextLine().trim();
    int b = Integer.parseInt(str_1);
    
    String str_2 = scan.nextLine().trim();
    int c = Integer.parseInt(str_2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    是不是, 茅塞顿开, 原来这是有规律的 !

    读取一行中的多个整数

    那如果是一行中有多个整数呢?

    也很简单, 不信你看 :

    Scanner scan = new Scanner(System.in);
    
    String str_0 = scan.nextLine();
    String[] line_list_0 = str_0.trim().split(" ");        
    ArrayList<Integer> arr_temp = new ArrayList<>();
    for(int i = 0; i < line_list_0.length; i++){
        arr_temp.add(Integer.parseInt(line_list_0[i]));
    }
    
    int a = arr_temp.get(0);
    int b = arr_temp.get(1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    同理, 读取一个整型数组 :

    Scanner scan = new Scanner(System.in);
    
    String str_0 = scan.nextLine();
    String[] line_list_0 = str_0.trim().split(" ");        
    ArrayList<Integer> arr = new ArrayList<>();
    for(int i = 0; i < line_list_0.length; i++){
        arr.add(Integer.parseInt(line_list_0[i]));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这里都不需要考虑是定长数组还是变长数组

    如果是写C语言的编程模板,就需要考虑变长数组需要动态分配内存的情况

    那么, 读取一个二维数组是怎样的呢?

    请看 :

    Scanner scan = new Scanner(System.in);
    
    String str_0 = scan.nextLine().trim();
    int q = Integer.parseInt(str_0);
    
    ArrayList<ArrayList<Integer>> arr = new ArrayList<>();
    for(int i = 0; i < q; i++){
        String str_3 = scan.nextLine();
        String[] line_list_3 = str_3.trim().split(" ");        
        ArrayList<Integer> temp_3 = new ArrayList<>();
        for(int j = 0; j < line_list_3.length; j++){
            temp_3.add(Integer.parseInt(line_list_3[j]));
        }
        arr.add(temp_3);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    这里也不需要考虑列数 (C语言是需要考虑的) , 其中, q 表示输入数据的行数

    其他的输入类型, 这里就不一一列举了

    三、解析输出

    相对解析输入来说, 解析输出就要简单很多

    打印一个整数

    int result = solution(n, vector);
    System.out.println(result);
    
    • 1
    • 2

    打印一个整数数组

    ArrayList<Integer> result = solution(n, q, nums, arr);
    
    for (int i = 0; i < result.size(); i++){
        System.out.println(result.get(i));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    打印二维数组也是同理, 这里留给读者自己尝试

    四、完整模板

    以下是其中一个例子:

    ## 输入描述
    第一行输入宝物的数量n(1
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    import java.util.ArrayList;
    import java.util.Scanner;
    
    class Main {
        public static void main(String[] args) {
            Scanner scan = new Scanner(System.in);
            
            String str_0 = scan.nextLine();
            String[] line_list_0 = str_0.trim().split(" ");        
            ArrayList<Integer> arr_temp = new ArrayList<>();
            for(int i = 0; i < line_list_0.length; i++){
                arr_temp.add(Integer.parseInt(line_list_0[i]));
            }
        
    
            int n = arr_temp.get(0);
    		int M = arr_temp.get(1);
    
            
            ArrayList<ArrayList<Integer>> vector = new ArrayList<>();
            for(int i = 0; i < n; i++){
                String str_2 = scan.nextLine();
                String[] line_list_2 = str_2.trim().split(" ");        
                ArrayList<Integer> temp_2 = new ArrayList<>();
                for(int j = 0; j < line_list_2.length; j++){
                    temp_2.add(Integer.parseInt(line_list_2[j]));
                }
                vector.add(temp_2);
            }
        
    
            scan.close();
    
            int result = solution(n, M, vector);
    
            System.out.println(result);
    
        }
    
        public static int solution(int n, int M, ArrayList<ArrayList> vector){
            int result = 0;
    
            // TODO: 请在此编写代码
    
            return result;
        }
    }
    
    
    • 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

    细心的同学应该发现了, 我这里都是以整数为例子, 其他类型的变量, 也是一样的, 只需判断输入数据的变量类型即可, 如:

    def is_float_num(str):
        s=str.split('.')
        if len(s)>2:
            return False
        else:
            for si in s:
                if not si.isdigit():
                    return False
            return True
    
    
    def is_number(i):
        try:
            int(i)
            return True
        except:
            return False
    
    def parse_input_one(item, var_name, input_var_idx = 0, assgin_var_type=None):
        var_type = None
        var_def = None
        var_input = None
        
        if assgin_var_type is not None:
            var_type = assgin_var_type
            var_def_ = f"{assgin_var_type} {var_name} = str_{input_var_idx}"
        else:
            if is_number(item):
                var_type = "int"
                var_def_ = f"int {var_name} = Integer.parseInt(str_{input_var_idx})"
            elif is_float_num(item):
                var_type = "float"
                var_def_ = f"float {var_name} = Float.parseFloat(str_{input_var_idx})"
            else:
                var_type = "String"
                var_def_ = f"String {var_name} = str_{input_var_idx}"
        
        var_def = f"{var_type} {var_name}"
        input_template = f"String str_{input_var_idx} = scan.nextLine().trim();"
        var_input = f"{input_template}\n\t\t{var_def_}"
        return var_type,var_name, var_def, var_input
    
    
    • 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

    我这里只考虑了常用的三种类型, 如果是其他类型, 可以通过参数assgin_var_type来控制.

    以上模板生成的脚本代码, 是使用python来实现的.

    总结

    1、深度分析数据后才能发现数据的规律

    一开始leader将这个jira分给我的时候, 我觉得这模板代码没法自动生成, 很是抗拒
    自己写了几个 python 的 oj 模板后才发现这确实是有规律可循的
    
    • 1
    • 2

    2、年轻人不要浮躁

    OJ比赛感兴趣的同学, 可以参加 CSDN编程竞赛第四期
    若发现 OJ 模板有任何问题, 可直接在评论区反馈

  • 相关阅读:
    vue+springboot,easyexcel的excel文件下载
    编程实例:眼镜店顾客档案管理系统软件,可以登记顾客信息查询历史记录,视力检查登记查询,配镜销售单开单打印
    判断是否相等 hasChanged
    基于System-Verilog的VGA彩条设计与仿真
    如何使用 ABAP 代码解析 XML 文件
    AWS SAA-C03 #99
    Qt QHeaderView 添加复选框
    vue轮播图使用swiper插件
    一线架构师开发总结:剖析并发编程+JVM性能,深入Tomcat与MySQL,离架构师更近一步!
    HTTP详解
  • 原文地址:https://blog.csdn.net/qq_44193969/article/details/126290082