#io #procon #procon

proconio

Easy IO library for competitive programming

20 releases

0.4.3 Apr 21, 2021
0.4.2 Mar 21, 2021
0.4.1 Apr 2, 2020
0.3.8 Apr 21, 2021
0.3.0 Jul 6, 2019

#87 in Command-line interface

Download history 208/week @ 2021-02-24 884/week @ 2021-03-03 355/week @ 2021-03-10 276/week @ 2021-03-17 296/week @ 2021-03-24 262/week @ 2021-03-31 165/week @ 2021-04-07 238/week @ 2021-04-14 545/week @ 2021-04-21 234/week @ 2021-04-28 151/week @ 2021-05-05 126/week @ 2021-05-12 511/week @ 2021-05-19 394/week @ 2021-05-26 214/week @ 2021-06-02 187/week @ 2021-06-09

1,369 downloads per month
Used in 5 crates

MIT/Apache

50KB
614 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 is input! macro.

Examples

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

# 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,
}

// now you can use n, m and l as variable.
println!("{} {} {}", n, m, l);
# assert_eq!(n, 32);
# assert_eq!(m, 54);
# assert_eq!(l, -23);

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

You can declare mutable variables like below:

# extern crate proconio;
# use proconio::source::auto::AutoSource;
use proconio::input;
# let source = AutoSource::from("32 54");

input! {
#   from source,
    n: u32,
    mut m: u32,
}

m += n; // OK: m is mutable
# assert_eq!(n, 32);
# assert_eq!(m, 86);

You can read an array or a matrix like this:

# extern crate proconio;
# use proconio::source::auto::AutoSource;
use proconio::input;
# let source = AutoSource::from("5 4 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5");

input! {
#    from source,
    n: usize,
    m: usize,
    a: [[i32; n]; m] // `a` is Vec<Vec<i32>>, (m, n)-matrix.
}
# assert_eq!(
#     a,
#     [
#         [1, 2, 3, 4, 5],
#         [1, 2, 3, 4, 5],
#         [1, 2, 3, 4, 5],
#         [1, 2, 3, 4, 5]
#     ]
# );

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.)

# extern crate proconio;
# use proconio::source::auto::AutoSource;
use proconio::input;
# let source = AutoSource::from("3 3 1 2 3 0 2 1 2");

input! {
#   from source,
    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:

# extern crate proconio;
# use proconio::source::auto::AutoSource;
use proconio::input;
use proconio::marker::{Bytes, Chars};
# let source = AutoSource::from("  string   chars\nbytes");

input! {
#     from source,
    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:

# extern crate proconio;
# use proconio::source::auto::AutoSource;
use proconio::input;
# let source = AutoSource::from("1 2 3 4 5");

input! {
#   from source,
    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.

# extern crate proconio;
# use proconio::source::auto::AutoSource;
use proconio::input;
# let source = AutoSource::from("4 3 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5");

input! {
#   from source,
    n: usize,
    m: usize,
    t: [([u32; m], i32); n],
}
# assert_eq!(
#     t,
#     [
#         (vec![1,1,1],1),
#         (vec![2,2,2],2),
#         (vec![3,3,3],3),
#         (vec![4,4,4],4),
#     ]
# );

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.

# extern crate proconio;
# use proconio::source::auto::AutoSource;
use proconio::input;
# let mut source = AutoSource::from("4 2 1 2 2 3 4 2 1 2 2 3 4");

input! {
#   from &mut source,
    n: usize,
}

for i in 0..n {
    input! {
#       from &mut source,
        m: usize,
        a: [i32; m],
    }
#   assert_eq!(a[0], if i % 2 == 0 { 1 } else { 3 });
#   assert_eq!(a[1], if i % 2 == 0 { 2 } else { 4 });
}

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.

# extern crate proconio;
# use proconio::source::auto::AutoSource;
use proconio::input;
use proconio::marker::Usize1;
# let mut source = AutoSource::from("4   1 3   3 4   6 1   5 3");

input! {
#   from &mut source,
    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]:

# #[cfg(feature = "derive")]
# {
# extern crate proconio;
use proconio::input;
# use proconio::source::auto::AutoSource;
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() {
#   let source = AutoSource::from("12 32 35");
    input! {
#       from source,
        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));
}
# }

#[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]:

# #[cfg(feature = "derive")]
# {
# extern crate proconio;
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.

# #[cfg(feature = "derive")]
# {
use proconio::fastout;

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

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

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

use proconio::fastout;

# fn some_function(_: String) -> impl Iterator<Item = String> { vec!["hello".to_string(), "world".to_string()].into_iter() }
# fn some_proc(x: &str) -> &str { x }

#[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.

# #[cfg(feature = "derive")]
# {
use proconio::fastout;

# fn some_function(_: String) -> impl Iterator<Item = String> { vec!["hello".to_string(), "world".to_string()].into_iter() }
# fn some_proc(x: &str) -> &str { x }

// 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

# #[cfg(feature = "derive")]
# {
# use proconio::fastout;
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

~125KB