User Guide
Overview

Overview

What is CPLib?

CPLib is a library written in C++ for processing test data of competitive programming problems. It helps you write clear and efficient checkers, interactors, validators, and generators.

Here is a basic example of a checker using CPLib:

chk.cpp
#include "cplib.hpp"
 
using namespace cplib;
 
CPLIB_REGISTER_CHECKER(chk);
 
void checker_main() {
  auto var_ans = var::i32("ans", -2000, 2000);
 
  int ouf_output = chk.ouf.read(var_ans);
  int ans_output = chk.ans.read(var_ans);
 
  if (ouf_output != ans_output) {
    chk.quit_wa(format("Expected %d, got %d", ans_output, ouf_output));
  }
 
  chk.quit_ac();
}

The above example demonstrates a core logic of CPLib: "variable input template". Using the "variable input template", you can save and reuse the logic of reading variables with the same restrictions. At the same time, based on the hierarchy of variable input, CPLib generates concise input stack information in case of errors.

Why use CPLib?

The advantages of the CPLib project over other similarly positioned libraries are mainly reflected in the following points.

Modernization

CPLib is developed using the newer C++ 17 standard and uses modern C++ syntax more frequently in its code. The standard library and features of modern C++ offer CPLib numerous syntactic sugars and enable fast implementation. Simultaneously, CPLib prioritizes utilizing the standard library instead of creating separate implementations, ensuring better compatibility with other libraries.

CPLib also has more modernized handling of some functional details. For example, when an input error occurs, CPLib returns a complete input stack trace, and when reporting output to a file, it uses the more popular JSON format instead of the XML format used by Testlib.

Scalability

CPLib's scalability is mainly reflected in two points: the design of the variable input template cplib::var::Var and customization for various evaluation platforms.

CPLib's variable input is based on the "variable input template", rather than Testlib-style readXYZ() series of functions that apply to various basic types. This makes it more convenient for CPLib to extend and combine input types, making the program more modular.

Here is a simple example that shows how to read a directed graph by combining and extending cplib::var::Var.

struct Edge {
  int32_t from, to;
 
  static auto read(var::Reader &in, int32_t n) -> Edge {
    auto [from, to] = in(var::i32("from", 1, n), var::i32("to", 1, n));
    if (from == to) in.fail("Self-loops are not allowed");
    return {from, to};
  }
};
 
struct Graph {
  int32_t n, m;
  std::vector<Edge> edges;
 
  static auto read(var::Reader &in) -> Graph {
    auto [n, m] = in(var::i32("n"), var::i32("m"));
    auto edges = in.read(var::ExtVar<Edge>("edge", n) * m);
    return {n, m, edges};
  }
};

CPLib's design encourages users to split complex input of a problem into several structures that implement static read functions, making the program simpler and easier to read.

On the other hand, CPLib takes into account the differences in some interfaces of various evaluation platforms and allows the use of initializer and reporter to customize the program's initialization and reporting methods. This way, you can achieve compatibility with upper-level evaluation platforms without modifying the CPLib source code.

Efficiency

benchmark_result

The test environment is as follows:

  • CPU: AMD Ryzen 7 6800H @ 3.2GHz.
  • OS: openSUSE Linux.
  • Compiler: g++ (GCC) 12.3.0.
  • Compiler flags: -O2.
  • C++ Standard Library: libstdc++.

After 1010 rounds of testing, Testlib efficiency was recorded as 100%, and CPLib's corresponding efficiency was calculated based on this value.

The dataset used for testing can be found in the GitHub repository (opens in a new tab).

Applicable Environments

CPLib provides assistance in four environments:

  • Checker: Checks answers of problem with multiple correct cases or detailed scoring requirements.
  • Interactor: Interact with participant's program in interactive problems.
  • Validator: Validates test input files with per-character precision in strict mode.
  • Generator: Generates data in batches.

Got Questions?

Please refer to our FAQ.