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 |
#121 in Command-line interface
2,284 downloads per month
Used in 8 crates
61KB
854 lines
proconio
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