23 releases

0.5.0 Jun 30, 2024
0.4.5 Jun 22, 2023
0.4.3 Apr 21, 2021
0.4.2 Mar 21, 2021
0.3.0 Jul 6, 2019

#122 in Command-line interface

Download history 847/week @ 2024-07-21 795/week @ 2024-07-28 713/week @ 2024-08-04 1198/week @ 2024-08-11 797/week @ 2024-08-18 943/week @ 2024-08-25 731/week @ 2024-09-01 729/week @ 2024-09-08 815/week @ 2024-09-15 903/week @ 2024-09-22 737/week @ 2024-09-29 309/week @ 2024-10-06 584/week @ 2024-10-13 646/week @ 2024-10-20 1020/week @ 2024-10-27 693/week @ 2024-11-03

3,021 downloads per month
Used in 8 crates

MIT/Apache

61KB
854 lines

proconio

crates.io docs.rs

Easy IO library for competitive programming.

proconio provides an easy way to read values from stdin (or other source). The main is input! macro.

The macro's user interface is basically the same with tanakh's input macro.

use proconio::input;

input! {
    n: u8,
    m: u32,
    l: i32,
}

// now you can use n, m and l as variable.
println!("{} {} {}", n, m, l);

For more details, see documentation.


lib.rs:

Easy IO library for competitive programming.

proconio provides an easy way to read values from stdin (or other source). The main feature provided by this crate is input! macro (and its family, input_interactive!, read_value!, and read_value_interactive!).

Examples

The macro's user interface is basically the same with tanakh's input macro.

use proconio::input;

input! {
    n: u8,
    m: u32,
    l: i32,
}

// now you can use n, m and l as variable.
println!("{} {} {}", n, m, l);

In above code, variables n, m and l are declared and stored values are read from stdin.

You can declare mutable variables like below:

use proconio::input;

input! {
    n: u32,
    mut m: u32,
}

m += n; // OK: m is mutable

You can read an array or a matrix like this:

use proconio::input;

input! {
    n: usize,
    m: usize,
    a: [[i32; n]; m] // `a` is Vec<Vec<i32>>, (m, n)-matrix.
}

If the first input is the length of the array, you can omit the length. This is the only way to read jagged array (an array of arrays of which the member arrays can be of different sizes) at once. (Of course you can use input! multiple times in for-loop to read such an array since input! can be used multiple times.)

use proconio::input;

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

// if you enter "3  3 1 2 3  0  2 1 2" to the stdin, the result is as follows.
assert_eq!(
    a,
    vec![
        vec![1, 2, 3],
        vec![],
        vec![1, 2],
    ]
);

Strings can be read as Vec<u8> or Vec<char>. Use Bytes and Chars to do so:

use proconio::input;
use proconio::marker::{Bytes, Chars};

input! {
    string: String, // read as String
    chars: Chars,   // read as Vec<char>
    bytes: Bytes,   // read as Vec<u8>
}

// if you enter "string chars bytes" to the stdin, they are like this.
assert_eq!(string, "string");
assert_eq!(chars, ['c', 'h', 'a', 'r', 's']);
assert_eq!(bytes, b"bytes");

You can read tuples:

use proconio::input;

input! {
    t: (i32, i32, i32, i32, i32),
}

// if you enter "1 2 3 4 5" to the stdin, `t` is like this.
assert_eq!(t, (1, 2, 3, 4, 5));

And you can freely combine these types.

use proconio::input;

input! {
    n: usize,
    m: usize,
    t: [([u32; m], i32); n],
}

You can use input! macro multiple times. For the second time, input! macro reads rest of input. It works even if the first input stops at the middle of a line. The subsequent reads will be started at the rest of the line. This may be helpful for problems where multiple datasets are given once.

use proconio::input;

input! {
    n: usize,
}

for i in 0..n {
    input! {
        m: usize,
        a: [i32; m],
    }
}

In addition to Chars and Bytes, Usize1 and Isize1 are also special types. They are read as usize and isize respectively, but the read value is decremented. It enables us to automatically convert 1-indexed vertices numbers to 0-indexed array indices.

use proconio::input;
use proconio::marker::Usize1;

input! {
    n: usize,
    edges: [(Usize1, Usize1); n],
}

// if you enter "4   1 3   3 4   6 1   5 3", the decremented value is stored.
assert_eq!(edges[0], (0, 2));
assert_eq!(edges[1], (2, 3));
assert_eq!(edges[2], (5, 0));
assert_eq!(edges[3], (4, 2));

Usize1 and Isize1 doesn't hold actual value, so you cannot have value of the type. Thus, they are only useful inside input! or #[derive_readable]. You can think the reason these types exist is to tell "how to read the value". This how-to can be defined through Readable trait. This trait doesn't require the output type to be the same with the implementor. Usize1 is implementing Readable trait, and there the type of read value is defined as usize. You can implement Readable for your own type to read values in customized way.

Finally, you can make your own types Readable using #[derive_readable] attribute. Types used in the struct are automatically translated to their output types, so a member declared as Usize1 has type usize as real struct.

Note: Using #[derive_readable] requires derive feature enabled. To do so, open your Cargo.toml and modify the line of proconio from:

proconio = "=(version)"

to:

proconio = { version = "=(version)", features = ["derive"] }

Example of #[derive_readable]:

use proconio::input;
use proconio::derive_readable;

// Unit struct can derive readable.  This generates a no-op for the reading.  Not ignoring
// the read value, but simply skip reading process.  You cannot use it to discard the input.
#[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() {
    input! {
        edge: Edge,
    }

    // if you enter "12 32 35" to the stdin, the values are as follows.
    assert_eq!(edge.from, 12);
    assert_eq!(edge.to, 31);
    assert_eq!(edge.weight, Weight);
    assert_eq!(edge.cost, Cost(35));
}

read_value! macro

read_value! macro is a macro used inside the input! macro, but using it directly is also useful in some cases. Typically when you don't need to store the value into a variable.

use proconio::source::auto::AutoSource;
use proconio::read_value;
let mut source = AutoSource::from("2 3 4");
let mut sum = 0;
for _ in 0..read_value!(from &mut source, usize) {
    sum += read_value!(from &mut source, u32);
}
assert_eq!(sum, 7);

Interactive version

The normal input! and read_value! macro reads the entire input at once in judge environment to optimize I/O performance. However this does not work well with interactive problems, since in those problems you need to communicate with the judge by writing and reading alternately.

In this case, you can manually create LineSource for stdin. There's handy interactive version of the macros doing exactly that. They are input_interactive! and read_value_interactive!.

The usage of those macros are exactly the same with the normal ones. Refer to the document of input! and read_value! for further information.

#[fastout]

If you import proconio::fastout, you can use #[fastout] attribute. Adding this attribute to your main(), your print! and println! become faster.

Note: Using #[proconio::fastout] requires derive feature enabled. To do so, open your Cargo.toml and modify the line of proconio from:

proconio = "=(version)"

to:

proconio = { version = "=(version)", features = ["derive"] }

Example of #[fastout]:

use proconio::fastout;

#[fastout]
fn main() {
    print!("{}{}, ", 'h', "ello"); // "hello"       (no newline)
    println!("{}!", "world");      // "world!\n"
    println!("{}", 123456789);     // "123456789\n"
}

Closures having print! or println! in #[fastout] function

You cannot create a closure containing print! or println! in #[fastout] function. This is because the closure becomes thread-unsafe since the closure refers the unlocked stdout introduced by #[fastout] attribute. If this were not prohibited, an invalid usage of such a closure would produce a very complex error messages. For example, std::thread::spawn(), which requires its argument closure to be thread-safe, causes a confusing error.

Yes, it is too conservative to make all of such closures compilation error because it is actually no problem to use such a closure only inside a single thread. This is related to a limitation in #[fastout] implementation.

For more technical details, see documentation for #[fastout] in proconio-derive.

How to resolve this error

Consider you want to run this code:

use proconio::fastout;

#[fastout]
fn main() {
    let thread = std::thread::spawn(|| {
        let x = 3;
        let y = x * x;
        println!("{}", y);
    });

    thread.join().unwrap();
}

You will get an error like below.

error: Closures in a #[fastout] function cannot contain `print!` or `println!` macro

note: If you want to run your entire logic in a thread having extended size of stack, you can
define a new function instead.  See documentation (https://.....) for more details.

note: This is because if you use this closure with `std::thread::spawn()` or any other
functions requiring `Send` for an argument closure, the compiler emits an error about thread
unsafety for our internal implementations.  If you are using the closure just in a single
thread, it's actually no problem, but we cannot check the trait bounds at the macro-expansion
time.  So for now, all closures having `print!` or `println!` is prohibited regardless of the
`Send` requirements.
 --> src/test.rs:10:9
   |
10 |         println!("{}", y);
   |         ^^^^^^^

If your print! is relying on the calculation in the thread, you can instead return the result from the thread.

use proconio::fastout;

#[fastout]
fn main() {
    let thread = std::thread::spawn(|| {
        let x = 3;
        x * x
    });

    let y = thread.join().unwrap();
    println!("{}", y);
}

If you are doing so complex job that it's too difficult to returning the results from your closure...

use proconio::fastout;


#[fastout]
fn main() {
    let context = "some context".to_string();
    let thread = std::thread::spawn(move || {
        // Use many println! and the order is very important
        // It's possible to aggregate the result and print it later, but it's not easy to read
        // and seems ugly.
        println!("this is header.");
        for (i, item) in some_function(context).enumerate() {
            print!("Item #{}: ", i);
            print!("{}", some_proc(&item));
            println!("({})", item);
        }
    });

    thread.join().unwrap();
}

...you can use a function instead.

use proconio::fastout;


// You can add #[fastout] here
#[fastout]
fn process(context: String) {
    // It's completely OK since this #[fastout] is a thing inside `process()`
    println!("this is header.");
    for (i, item) in some_function(context).enumerate() {
        print!("Item #{}: ", i);
        print!("{}", some_proc(&item));
        println!("({})", item);
    }
}

// You must not add #[fastout] here!  It causes deadlock.
// #[fastout]
fn main() {
    let context = "some context".to_string();
    let thread = std::thread::spawn(move || process(context));
    thread.join().unwrap();
}

Important Note: If you spawn a new thread which runs another function annotated with #[fastout], you must not add #[fastout] to the caller. If you add #[fastout] in caller too, then the caller has the lock for the stdout, and so callee cannot acquire the lock forever --- deadlock. This is not the case when the caller and callee is executed in the same thread, since the lock of stdout is reentrant. We cannot warn about this kind of deadlock since we don't know annotations attached to the function to be called. (In the above example, we can't know whether the function process() has #[fastout] attribute or not.)

If your code is so complex that you cannot avoid deadlock, you should give up using #[fastout] and simply use println! or manually handle your stdout in usual Rust way.

Issues of printing order

#[fastout] enables buffering to stdout, so if you print something in other functions between two prints in main, the order of printing may differ. In other words, the below example

fn foo() { println!("between"); }
#[fastout]
fn main() {
    println!("hello");
    foo();
    println!("world");
}

likely prints like

between
hello
world

If you don't like this behavior, you can remove #[fastout] from your main().

Dependencies

~230KB