proconio

repository·master·Indexed 41 days ago

https://github.com/statiolake/proconio-rs

An easy-to-use IO library for Rust tailored for competitive programming environments like AtCoder. Version 0.6.0 provides the `input!` and `read_value!` macros for declarative and imperative input reading, support for arrays, matrices, and custom types via `#[derive_readable]`, and performance optimizations such as `input_once!` for non-interactive problems and `#[fastout]` for buffered stdout.

Tokens
5.6K
Snippets
18
Records
23
Agent score
49%

What's inside proconio

  1. Overview of proconio and proconio-derive

    master

    proconio is a library designed for easy input/output (IO) in competitive programming, specifically optimized for use with AtCoder. It is split into two main components:

    1. proconio: The core library providing easy IO utilities.
    2. proconio-derive: A companion crate providing procedural macros for easier input handling via derivation.
  2. Use proconio-derive for procedural macros

    master
    The proconio-derive crate provides procedural macros for use with the proconio library. It allows for more ergonomic input parsing in competitive programming contexts by providing derive macros that can be applied to structs or other data types to automate the reading of input data.
  3. Use the input! macro to read values from stdin

    master

    The input! macro is the primary interface for proconio. It allows you to declare variables and read their values from standard input (stdin) in a single block. The syntax is modeled after tanakh's input macro, where you specify a variable name followed by its type.

    Once the input! block is executed, the declared variables are available in the local scope for use.

    use proconio::input;
    
    input! {
        n: u8,
        m: u32,
        l: i32,
    }
    
    // now you can use n, m and l as variable.
    println!("{} {} {}", n, m, l);
  4. Understand the different input Source types

    master

    Proconio uses the Source trait to define how input data is provided to the input! macro. There are three main types of sources:

    1. OnceSource: Reads the entire input at once. It is very fast but requires you to signal EOF (Ctrl-D on Unix, Ctrl-Z on Windows) after the input. It is used by the input_once! macro.
    2. LineSource: Reads input line by line. This is ideal for local debugging and interactive testing where you press Enter after each line. It is used by the input! macro.
    3. AutoSource: A compatibility source that switches behavior based on the build profile: LineSource in debug builds and OnceSource in release builds.

    Note: To ensure consistent behavior between local testing and judge servers, the input! macro always uses LineSource and input_once! always uses OnceSource, regardless of the build profile. You should only use AutoSource if you explicitly want profile-dependent behavior.

    # extern crate proconio;
    use proconio::source::auto::AutoSource;
    use proconio::input;
    
    let source = AutoSource::from("32 54 -23");
    input! {
        from source,
        n: u8,
        m: u32,
        l: i32,
    }
  5. Read variable-length arrays (VLA) into `Vec`

    master

    To read a sequence of elements into a Vec, use the [Type] syntax within the input! macro. This is a Variable Length Array (VLA) pattern where the length is determined at runtime based on the input stream or previously read variables.

    Example: a: [i32] will read elements until the end of the source or until the structure is satisfied.

    input! {
        from source,
        n: usize,
        a: [[i32]; n],
    }
  6. Use `input_once!` for faster non-interactive I/O

    master

    For non-interactive problems where performance is critical, use input_once! or read_value_once!. These macros read the entire input at once into a buffer, which is faster than the default line-by-line reading.

    Restrictions

    • No Interactive Problems: The first invocation blocks until EOF. You must signal EOF (e.g., Ctrl-D on Unix) if typing manually.
    • No Mixing: You cannot mix input_once!/read_value_once! with line-by-line macros (input!, read_value!, or is_stdin_empty!) in the same program. Doing so will cause a runtime panic.
    • No from source: input_once! does not support the from source syntax. Use input! if you need to provide a custom source.
  7. Use `RuntimeReadable` for custom complex types

    master

    If you need to read a type that depends on runtime values (like a Vec whose size is determined by a previously read variable), you can implement the RuntimeReadable trait. In the input! macro, you use the with keyword to pass an instance of your custom reader.

    Example pattern:

    1. Define a struct that implements RuntimeReadable.
    2. Use with MyReader::new(n) inside the input! macro.
    // Example of using a custom runtime reader
    input! {
        from &mut source,
        n: usize,
        v: with VecReadable::<crate::marker::Usize1>::new(n),
    }
  8. Use the `input!` macro to read values

    master

    The input! macro is the primary way to read values from stdin or a custom source and declare them as variables. By default, it reads line-by-line, making it suitable for interactive problems.

    Syntax

    input! {
        from source,          // optional: defaults to stdin
        (mut) variable: type, // mut is optional
        ...
    }

    Key Features

    • Mutability: Use mut variable: type to declare a mutable variable.
    • Arrays and Matrices: You can read arrays or matrices. If the first input is the length, you can omit the length in the type definition to read jagged arrays.
    • Tuples: Supports reading into tuples: t: (i32, i32).
    • Custom Sources: Use from source to read from an object implementing the Source trait (e.g., AutoSource). To prevent moving the source, use from &mut source.
    use proconio::input;
    use proconio::source::auto::AutoSource;
    
    let source = AutoSource::from("32 54 -23");
    
    input! {
        from source,
        n: u8,
        m: u32,
        l: i32,
    }
    
    // n, m, and l are now available as variables
  9. Specify a custom source in the `input!` macro

    master

    By default, input! uses LineSource with stdin, and input_once! uses OnceSource with stdin. If you want to provide input from a specific source (like a string literal or a custom buffer), use the from source syntax inside the macro.

    Both OnceSource and LineSource implement From<&str>, allowing you to create them directly from string literals. You can also create them from any type implementing BufRead using OnceSource::new() or LineSource::new().

    # extern crate proconio;
    use proconio::source::auto::AutoSource;
    use proconio::input;
    
    let source = AutoSource::from("32 54 -23");
    input! {
        from source,
        n: u8,
        m: u32,
        l: i32,
    }
  10. Define custom readable types with `#[derive_readable]`

    master

    You can make your own structs Readable using the #[derive_readable] attribute (requires the derive feature). This allows you to use your custom types directly inside input! or read_value! macros.

    When using #[derive_readable], types used in the struct fields are automatically translated to their actual output types. For example, if a field is declared as proconio::marker::Usize1, the resulting struct field will be of type usize.

    Example

    #[cfg(feature = "derive")]
    {
        use proconio::input;
        use proconio::derive_readable;
        use proconio::marker::Usize1;
    
        #[derive_readable]
        struct Weight;
    
        #[derive_readable]
        struct Cost(i32);
    
        #[derive_readable]
        struct Edge {
            from: usize,
            to: Usize1, // The real Edge::to has type usize.
            weight: Weight,
            cost: Cost,
        }
    
        fn main() {
            input! {
                edge: Edge,
            }
        }
    }
    #[cfg(feature = "derive")]
    {
        extern crate proconio;
        use proconio::input;
        use proconio::source::auto::AutoSource;
        use proconio::derive_readable;
    
        #[derive_readable]
        #[derive(PartialEq, Debug)]
        struct Weight;
    
        #[derive_readable]
        #[derive(PartialEq, Debug)]
        struct Cost(i32);
    
        #[derive_readable]
        #[derive(Debug)]
        struct Edge {
            from: usize,
            to: proconio::marker::Usize1, // The real Edge::to has type usize.
            weight: Weight,
            cost: Cost,
        }
    
        fn main() {
        # let source = AutoSource::from("12 32 35");
            input! {
        #       from source,
                edge: Edge,
            }
    
        #     assert_eq!(edge.from, 12);
        #     assert_eq!(edge.to, 31);
        #     assert_eq!(edge.weight, Weight);
        #     assert_eq!(edge.cost, Cost(35));
        }
    }
  11. Speed up output with `#[fastout]`

    master

    If you enable the derive feature in your Cargo.toml, you can use the #[fastout] attribute to speed up print! and println! calls by using buffered output.

    Setup

    In Cargo.toml:

    proconio = { version = "...", features = ["derive"] }

    Usage

    use proconio::fastout;
    
    #[fastout]
    fn main() {
        println!("Hello, world!");
    }

    Important Limitations

    • Thread Safety: You cannot create a closure containing print! or println! inside a #[fastout] function (e.g., via std::thread::spawn), as the closure becomes thread-unsafe due to the internal unlocked stdout.
    • Deadlocks: If you spawn a new thread that runs a function annotated with #[fastout], you must not annotate the caller function with #[fastout]. Doing so will cause a deadlock because the caller will hold the stdout lock that the callee needs.
    • Printing Order: Because #[fastout] uses buffering, the order of output between main and other functions might differ from standard execution.
    #[cfg(feature = "derive")]
    {
        use proconio::fastout;
    
        #[fastout]
        fn main() {
            print!("{}{}, ", 'h', "ello"); // "hello" (no newline)
            println!("{}!", "world");      // "world!\n"
            println!("{}", 123456789);     // "123456789\n"
        }
    }
  12. Read arrays and matrices with `input!`

    master

    You can read arrays and multi-dimensional matrices directly using the input! macro.

    Fixed-size Matrix

    To read an $m imes n$ matrix into a Vec<Vec<T>>:

    input! {
        n: usize,
        m: usize,
        a: [[i32; n]; m]
    }

    Jagged Arrays

    If the input contains lengths for each sub-array, you can omit the inner length to read jagged arrays:

    input! {
        n: usize,
        a: [[i32]; n]
    }

    This reads n arrays, where each array's size is determined by the next available tokens in the input.

    use proconio::input;
    use proconio::source::auto::AutoSource;
    
    let source = AutoSource::from("3 3 1 2 3 0 2 1 2");
    
    input! {
        from source,
        n: usize,
        a: [[i32]; n],
    }
    
    // a is vec![vec![1, 2, 3], vec![], vec![1, 2]]