├── templates
├── classic.rs
├── single.rs
├── multi_eof.rs
├── interactive.rs
├── multi_number.rs
├── main
│ ├── main.rs
│ ├── stdin.rs
│ ├── stdout.rs
│ ├── file_in.rs
│ ├── file_out.rs
│ └── regex.rs
├── build.rs
├── main.rs
├── Cargo.toml
├── sites
│ ├── meta.rs
│ ├── default.rs
│ └── codeforces.rs
└── tester.rs
├── tasks
└── a123233
│ ├── tests
│ ├── 1.out
│ ├── 2.out
│ ├── 3.out
│ ├── 4.out
│ ├── 1.in
│ ├── 2.in
│ ├── 3.in
│ └── 4.in
│ ├── build.rs
│ ├── Cargo.toml
│ └── src
│ ├── main.rs
│ └── tester.rs
├── algo_lib
├── src
│ ├── io
│ │ ├── mod.rs
│ │ ├── output.rs
│ │ └── input.rs
│ ├── misc
│ │ ├── mod.rs
│ │ ├── test_type.rs
│ │ └── run_parallel.rs
│ └── lib.rs
└── Cargo.toml
├── Cargo.toml
├── main
├── Cargo.toml
├── .cargo
│ └── config.toml
└── src
│ └── main.rs
├── README.md
├── .gitignore
├── .github
└── workflows
│ └── rust.yml
└── archive
└── 2021
└── 12
└── 14.12.2021 - Codeforces Beta Round #4 (Дивизион 2)
└── a_arbuz.rs
/templates/classic.rs:
--------------------------------------------------------------------------------
1 | Classic
--------------------------------------------------------------------------------
/templates/single.rs:
--------------------------------------------------------------------------------
1 | Single
--------------------------------------------------------------------------------
/tasks/a123233/tests/1.out:
--------------------------------------------------------------------------------
1 | Yes
2 |
--------------------------------------------------------------------------------
/tasks/a123233/tests/2.out:
--------------------------------------------------------------------------------
1 | No
2 |
--------------------------------------------------------------------------------
/tasks/a123233/tests/3.out:
--------------------------------------------------------------------------------
1 | Yes
2 |
--------------------------------------------------------------------------------
/tasks/a123233/tests/4.out:
--------------------------------------------------------------------------------
1 | No
2 |
--------------------------------------------------------------------------------
/templates/multi_eof.rs:
--------------------------------------------------------------------------------
1 | MultiEof
--------------------------------------------------------------------------------
/tasks/a123233/tests/1.in:
--------------------------------------------------------------------------------
1 | 123233
2 |
--------------------------------------------------------------------------------
/tasks/a123233/tests/2.in:
--------------------------------------------------------------------------------
1 | 123234
2 |
--------------------------------------------------------------------------------
/tasks/a123233/tests/3.in:
--------------------------------------------------------------------------------
1 | 323132
2 |
--------------------------------------------------------------------------------
/tasks/a123233/tests/4.in:
--------------------------------------------------------------------------------
1 | 500000
2 |
--------------------------------------------------------------------------------
/templates/interactive.rs:
--------------------------------------------------------------------------------
1 | Interactive
--------------------------------------------------------------------------------
/templates/multi_number.rs:
--------------------------------------------------------------------------------
1 | MultiNumber
--------------------------------------------------------------------------------
/algo_lib/src/io/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod input;
2 | pub mod output;
3 |
--------------------------------------------------------------------------------
/algo_lib/src/misc/mod.rs:
--------------------------------------------------------------------------------
1 | pub mod run_parallel;
2 | pub mod test_type;
3 |
--------------------------------------------------------------------------------
/templates/main/main.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | $INPUT
3 | $OUTPUT
4 | crate::solution::run(input, output);
5 | }
6 |
--------------------------------------------------------------------------------
/templates/main/stdin.rs:
--------------------------------------------------------------------------------
1 | let mut sin = std::io::stdin();
2 | let input = algo_lib::io::input::Input::new(&mut sin);
3 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = [
3 | "tasks/a123233",
4 | "main",
5 | "algo_lib",
6 | ]
7 | resolver = "2"
8 |
--------------------------------------------------------------------------------
/templates/main/stdout.rs:
--------------------------------------------------------------------------------
1 | let mut stdout = std::io::stdout();
2 | let output = algo_lib::io::output::Output::new(&mut stdout);
3 |
--------------------------------------------------------------------------------
/algo_lib/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "algo_lib"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 | rayon = "~1.7"
8 |
--------------------------------------------------------------------------------
/algo_lib/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![allow(clippy::too_many_arguments)]
2 | #![allow(clippy::type_complexity)]
3 |
4 | pub mod io;
5 | pub mod misc;
6 |
--------------------------------------------------------------------------------
/templates/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | rust_competitive_helper_util::build::build_several_libraries(&["algo_lib".to_owned()], false);
3 | }
4 |
--------------------------------------------------------------------------------
/tasks/a123233/build.rs:
--------------------------------------------------------------------------------
1 | fn main() {
2 | rust_competitive_helper_util::build::build_several_libraries(&["algo_lib".to_owned()], false);
3 | }
4 |
--------------------------------------------------------------------------------
/main/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "main"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 | rayon = "~1.7"
8 | regex = "~1.9"
9 |
--------------------------------------------------------------------------------
/templates/main/file_in.rs:
--------------------------------------------------------------------------------
1 | let mut in_file = std::fs::File::open("$IN_FILE").unwrap();
2 | let input = crate::algo_lib::io::input::Input::new(&mut in_file);
3 |
--------------------------------------------------------------------------------
/templates/main/file_out.rs:
--------------------------------------------------------------------------------
1 | let mut out_file = std::fs::File::create("$OUT_FILE").unwrap();
2 | let output = crate::algo_lib::io::output::Output::new(&mut out_file);
3 |
--------------------------------------------------------------------------------
/algo_lib/src/misc/test_type.rs:
--------------------------------------------------------------------------------
1 | pub enum TestType {
2 | Single,
3 | MultiNumber,
4 | MultiEof,
5 | }
6 |
7 | pub enum TaskType {
8 | Classic,
9 | Interactive,
10 | }
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # example-contests-workspace
2 |
3 | Repository for writing contests in Rust with rust-competitive-helper.
4 |
5 | More info on how to use rust-competitive-helper for contests [here](https://github.com/rust-competitive-helper/rust-competitive-helper).
6 |
--------------------------------------------------------------------------------
/main/.cargo/config.toml:
--------------------------------------------------------------------------------
1 | # 64 bit MSVC
2 | [target.x86_64-pc-windows-msvc]
3 | rustflags = [
4 | "-C", "link-arg=/STACK:1000000000"
5 | ]
6 |
7 | # 64 bit Mingw
8 | [target.x86_64-pc-windows-gnu]
9 | rustflags = [
10 | "-C", "link-arg=-Wl,--stack,1000000000"
11 | ]
12 |
--------------------------------------------------------------------------------
/templates/main.rs:
--------------------------------------------------------------------------------
1 | //$JSON
2 |
3 | use algo_lib::io::input::Input;
4 | use algo_lib::io::output::Output;
5 | use algo_lib::misc::test_type::TaskType;
6 |
7 | $SOLVE
8 |
9 | //START MAIN
10 | mod tester;
11 |
12 | fn main() {
13 | tester::run_tests();
14 | }
15 | //END MAIN
16 |
--------------------------------------------------------------------------------
/templates/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "$TASK"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 | algo_lib = { path = "../../algo_lib" }
8 |
9 | [build-dependencies]
10 | rust_competitive_helper_util = {git = "https://github.com/rust-competitive-helper/rust-competitive-helper"}
11 |
--------------------------------------------------------------------------------
/tasks/a123233/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "a123233"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 | algo_lib = { path = "../../algo_lib" }
8 |
9 | [build-dependencies]
10 | rust_competitive_helper_util = {git = "https://github.com/rust-competitive-helper/rust-competitive-helper"}
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | /target/
4 |
5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
7 | Cargo.lock
8 |
9 | # These are backup files generated by rustfmt
10 | **/*.rs.bk
11 |
12 |
13 | # More files:
14 | # It is autogenerated, no need to save in repo
15 | main/src/main.rs
--------------------------------------------------------------------------------
/.github/workflows/rust.yml:
--------------------------------------------------------------------------------
1 | name: Cargo Build & Test
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | env:
8 | CARGO_TERM_COLOR: always
9 |
10 | jobs:
11 | build_and_test:
12 | name: Rust project - latest
13 | runs-on: ubuntu-latest
14 | strategy:
15 | matrix:
16 | toolchain:
17 | - stable
18 | - beta
19 | - nightly
20 | steps:
21 | - uses: actions/checkout@v4
22 | - run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
23 | - run: cargo build --verbose
24 | - run: cargo test --verbose
25 |
--------------------------------------------------------------------------------
/templates/sites/meta.rs:
--------------------------------------------------------------------------------
1 | use algo_lib::misc::run_parallel::run_parallel;
2 | use std::sync::MutexGuard;
3 |
4 | type PreCalc = ();
5 |
6 | fn solve(mut input: MutexGuard, out: &mut Output, test_case: usize, _data: &PreCalc) {
7 | $CARET
8 | drop(input);
9 | out.print_line((format!("Case #{}:", test_case),));
10 | }
11 |
12 | pub static TASK_TYPE: TaskType = TaskType::Classic;
13 |
14 | pub(crate) fn run(input: Input, mut output: Output) -> bool {
15 | let pre_calc = ();
16 | let is_exhausted = run_parallel(input, &mut output, true, pre_calc, solve);
17 | output.flush();
18 | is_exhausted
19 | }
20 |
--------------------------------------------------------------------------------
/templates/main/regex.rs:
--------------------------------------------------------------------------------
1 | let paths = std::fs::read_dir(".").unwrap();
2 | let mut result = None;
3 | let mut last_accessed = None;
4 | let re = regex::Regex::new("$PATTERN").unwrap();
5 | for path in paths {
6 | let path = path.unwrap();
7 | let cur_accessed = path.metadata().unwrap().accessed().unwrap();
8 | let path = path.path();
9 | let cur_name = path.file_name().unwrap().to_str().unwrap();
10 | if re.is_match(cur_name) {
11 | if last_accessed.is_none() || cur_accessed > last_accessed.unwrap() {
12 | result = Some(cur_name.to_string());
13 | last_accessed = Some(cur_accessed);
14 | }
15 | }
16 | }
17 | let mut in_file = std::fs::File::open(result.unwrap()).unwrap();
18 | let input = crate::algo_lib::io::input::Input::new(&mut in_file);
19 |
--------------------------------------------------------------------------------
/archive/2021/12/14.12.2021 - Codeforces Beta Round #4 (Дивизион 2)/a_arbuz.rs:
--------------------------------------------------------------------------------
1 | //{"name":"A. Арбуз","group":"Codeforces - Codeforces Beta Round #4 (Дивизион 2)","url":"https://codeforces.com/problemset/problem/4/A","interactive":false,"timeLimit":1000,"tests":[{"input":"8\n","output":"YES\n"}],"testType":"single","input":{"type":"stdin","fileName":null,"pattern":null},"output":{"type":"stdout","fileName":null,"pattern":null},"languages":{"java":{"taskClass":"AArbuz"}}}
2 |
3 | use algo_lib::io::input::Input;
4 | use algo_lib::io::output::output;
5 | use algo_lib::{out, out_line};
6 |
7 | fn solve(input: &mut Input, _test_case: usize) {
8 | let n: usize = input.read();
9 | let res = if n % 2 == 0 && n > 2 { "YES" } else { "NO" };
10 | out_line!(res);
11 | }
12 |
13 | pub(crate) fn run(mut input: Input) -> bool {
14 | solve(&mut input, 1);
15 | output().flush();
16 | input.skip_whitespace();
17 | !input.peek().is_some()
18 | }
19 |
20 | //START MAIN
21 | mod tester;
22 |
23 | fn main() {
24 | tester::run_tests();
25 | }
26 | //END MAIN
27 |
--------------------------------------------------------------------------------
/templates/sites/default.rs:
--------------------------------------------------------------------------------
1 | use algo_lib::misc::test_type::TestType;
2 |
3 | type PreCalc = ();
4 |
5 | fn solve(input: &mut Input, out: &mut Output, _test_case: usize, _data: &mut PreCalc) {
6 | $CARET
7 | }
8 |
9 | pub static TEST_TYPE: TestType = TestType::$INVOKE;
10 | pub static TASK_TYPE: TaskType = TaskType::$INTERACTIVE;
11 |
12 | pub(crate) fn run(mut input: Input, mut output: Output) -> bool {
13 | let mut pre_calc = ();
14 |
15 | match TEST_TYPE {
16 | TestType::Single => solve(&mut input, &mut output, 1, &mut pre_calc),
17 | TestType::MultiNumber => {
18 | let t = input.read();
19 | for i in 1..=t {
20 | solve(&mut input, &mut output, i, &mut pre_calc);
21 | }
22 | }
23 | TestType::MultiEof => {
24 | let mut i = 1;
25 | while input.peek().is_some() {
26 | solve(&mut input, &mut output, i, &mut pre_calc);
27 | i += 1;
28 | }
29 | }
30 | }
31 | output.flush();
32 | match TASK_TYPE {
33 | TaskType::Classic => {
34 | input.is_empty()
35 | }
36 | TaskType::Interactive => true,
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/templates/sites/codeforces.rs:
--------------------------------------------------------------------------------
1 | use algo_lib::misc::test_type::TestType;
2 |
3 | type PreCalc = ();
4 |
5 | fn solve(input: &mut Input, out: &mut Output, _test_case: usize, _data: &mut PreCalc) {
6 | $CARET
7 | }
8 |
9 | pub static TEST_TYPE: TestType = TestType::MultiNumber;
10 | pub static TASK_TYPE: TaskType = TaskType::$INTERACTIVE;
11 |
12 | pub(crate) fn run(mut input: Input, mut output: Output) -> bool {
13 | let mut pre_calc = ();
14 |
15 | match TEST_TYPE {
16 | TestType::Single => solve(&mut input, &mut output, 1, &mut pre_calc),
17 | TestType::MultiNumber => {
18 | let t = input.read();
19 | for i in 1..=t {
20 | solve(&mut input, &mut output, i, &mut pre_calc);
21 | }
22 | }
23 | TestType::MultiEof => {
24 | let mut i = 1;
25 | while input.peek().is_some() {
26 | solve(&mut input, &mut output, i, &mut pre_calc);
27 | i += 1;
28 | }
29 | }
30 | }
31 | output.flush();
32 | match TASK_TYPE {
33 | TaskType::Classic => {
34 | input.is_empty()
35 | }
36 | TaskType::Interactive => true,
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/tasks/a123233/src/main.rs:
--------------------------------------------------------------------------------
1 | //{"name":"A - 123233","group":"AtCoder - AtCoder Beginner Contest 380","url":"https://atcoder.jp/contests/abc380/tasks/abc380_a","interactive":false,"timeLimit":2000,"tests":[{"input":"123233\n","output":"Yes\n"},{"input":"123234\n","output":"No\n"},{"input":"323132\n","output":"Yes\n"},{"input":"500000\n","output":"No\n"}],"testType":"single","input":{"type":"stdin","fileName":null,"pattern":null},"output":{"type":"stdout","fileName":null,"pattern":null},"languages":{"java":{"taskClass":"A123233"}}}
2 |
3 | use algo_lib::io::input::Input;
4 | use algo_lib::io::output::Output;
5 | use algo_lib::misc::test_type::TaskType;
6 |
7 | use algo_lib::misc::test_type::TestType;
8 |
9 | type PreCalc = ();
10 |
11 | fn solve(input: &mut Input, out: &mut Output, _test_case: usize, _data: &mut PreCalc) {
12 | let mut n = input.read_size();
13 |
14 | let mut d = [0; 6];
15 | for i in 0..6 {
16 | d[i] = n % 10;
17 | n /= 10;
18 | }
19 | d.sort();
20 | out.print_line(if d == [1, 2, 2, 3, 3, 3] {
21 | "Yes"
22 | } else {
23 | "No"
24 | });
25 | }
26 |
27 | pub static TEST_TYPE: TestType = TestType::Single;
28 | pub static TASK_TYPE: TaskType = TaskType::Classic;
29 |
30 | pub(crate) fn run(mut input: Input, mut output: Output) -> bool {
31 | let mut pre_calc = ();
32 |
33 | match TEST_TYPE {
34 | TestType::Single => solve(&mut input, &mut output, 1, &mut pre_calc),
35 | TestType::MultiNumber => {
36 | let t = input.read();
37 | for i in 1..=t {
38 | solve(&mut input, &mut output, i, &mut pre_calc);
39 | }
40 | }
41 | TestType::MultiEof => {
42 | let mut i = 1;
43 | while input.peek().is_some() {
44 | solve(&mut input, &mut output, i, &mut pre_calc);
45 | i += 1;
46 | }
47 | }
48 | }
49 | output.flush();
50 | match TASK_TYPE {
51 | TaskType::Classic => {
52 | input.is_empty()
53 | }
54 | TaskType::Interactive => true,
55 | }
56 | }
57 |
58 |
59 | //START MAIN
60 | mod tester;
61 |
62 | fn main() {
63 | tester::run_tests();
64 | }
65 | //END MAIN
66 |
--------------------------------------------------------------------------------
/algo_lib/src/misc/run_parallel.rs:
--------------------------------------------------------------------------------
1 | use crate::io::input::Input;
2 | use crate::io::output::Output;
3 | use std::io::Write;
4 | use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
5 | use std::sync::{Arc, Mutex, MutexGuard, TryLockError};
6 | use std::thread::{available_parallelism, scope, yield_now, Builder};
7 |
8 | pub fn run_parallel
(
9 | mut input: Input,
10 | output: &mut Output,
11 | do_parallel: bool,
12 | pre_calc: P,
13 | run: impl Fn(MutexGuard, &mut Output, usize, &P) + Send + Sync + 'static + Copy,
14 | ) -> bool
15 | where
16 | for<'a> &'a P: Send,
17 | {
18 | let t = input.read_size();
19 | let tests_remaining = AtomicUsize::new(t);
20 | let input = Arc::new(Mutex::new(input));
21 | let free_slots = AtomicUsize::new(available_parallelism().unwrap().get() - 1);
22 | let input_locked = AtomicBool::new(false);
23 | scope(|s| {
24 | let mut handles = Vec::with_capacity(t);
25 | for i in 1..=t {
26 | eprintln!("Test {} started", i);
27 | let tr = &tests_remaining;
28 | let inp = input.clone();
29 | let pre_calc = &pre_calc;
30 | free_slots.fetch_sub(1, Ordering::Relaxed);
31 | input_locked.store(true, Ordering::Relaxed);
32 | let il = &input_locked;
33 | let fs = &free_slots;
34 | let builder = Builder::new().stack_size(1_000_000_000);
35 | let handle = builder.spawn_scoped(s, move || {
36 | let lock = inp.lock().unwrap();
37 | il.store(false, Ordering::Relaxed);
38 | let mut res = Vec::new();
39 | let mut output = Output::new(&mut res);
40 | run(lock, &mut output, i, pre_calc);
41 | eprintln!(
42 | "Test {} done, {} tests remaining",
43 | i,
44 | tr.fetch_sub(1, Ordering::Relaxed) - 1
45 | );
46 | output.flush();
47 | fs.fetch_add(1, Ordering::Relaxed);
48 | res
49 | });
50 | if do_parallel {
51 | while input_locked.load(Ordering::Relaxed) {
52 | yield_now();
53 | }
54 | while let Err(err) = input.try_lock() {
55 | match err {
56 | TryLockError::Poisoned(poison) => {
57 | panic!("Poisoned lock: {:?}", poison);
58 | }
59 | TryLockError::WouldBlock => {
60 | yield_now();
61 | }
62 | }
63 | }
64 | while free_slots.load(Ordering::Relaxed) == 0 {
65 | yield_now();
66 | }
67 | handles.push(handle.unwrap());
68 | } else {
69 | let res = handle.unwrap().join().unwrap();
70 | output.write_all(&res).unwrap();
71 | }
72 | }
73 | for handle in handles {
74 | let res = handle.join().unwrap();
75 | output.write_all(&res).unwrap();
76 | }
77 | });
78 | let res = input.lock().unwrap().is_empty();
79 | res
80 | }
81 |
--------------------------------------------------------------------------------
/algo_lib/src/io/output.rs:
--------------------------------------------------------------------------------
1 | use std::io::Write;
2 |
3 | pub struct Output<'s> {
4 | output: &'s mut dyn Write,
5 | buf: Vec,
6 | at: usize,
7 | auto_flush: bool,
8 | }
9 |
10 | impl<'s> Output<'s> {
11 | const DEFAULT_BUF_SIZE: usize = 4096;
12 |
13 | pub fn new(output: &'s mut dyn Write) -> Self {
14 | Self {
15 | output,
16 | buf: vec![0; Self::DEFAULT_BUF_SIZE],
17 | at: 0,
18 | auto_flush: false,
19 | }
20 | }
21 |
22 | pub fn new_with_auto_flush(output: &'s mut dyn Write) -> Self {
23 | Self {
24 | output,
25 | buf: vec![0; Self::DEFAULT_BUF_SIZE],
26 | at: 0,
27 | auto_flush: true,
28 | }
29 | }
30 |
31 | pub fn flush(&mut self) {
32 | if self.at != 0 {
33 | self.output.write_all(&self.buf[..self.at]).unwrap();
34 | self.output.flush().unwrap();
35 | self.at = 0;
36 | self.output.flush().expect("Couldn't flush output");
37 | }
38 | }
39 |
40 | pub fn print(&mut self, s: T) {
41 | s.write(self);
42 | }
43 |
44 | pub fn print_line(&mut self, s: T) {
45 | self.print(s);
46 | self.put(b'\n');
47 | }
48 |
49 | pub fn put(&mut self, b: u8) {
50 | self.buf[self.at] = b;
51 | self.at += 1;
52 | if self.at == self.buf.len() {
53 | self.flush();
54 | }
55 | }
56 |
57 | pub fn maybe_flush(&mut self) {
58 | if self.auto_flush {
59 | self.flush();
60 | }
61 | }
62 |
63 | pub fn print_per_line(&mut self, arg: &[T]) {
64 | for i in arg {
65 | i.write(self);
66 | self.put(b'\n');
67 | }
68 | }
69 |
70 | pub fn print_iter>(&mut self, iter: I) {
71 | let mut first = true;
72 | for e in iter {
73 | if first {
74 | first = false;
75 | } else {
76 | self.put(b' ');
77 | }
78 | e.write(self);
79 | }
80 | }
81 |
82 | pub fn print_iter_ref<'a, T: 'a + Writable, I: Iterator- >(&mut self, iter: I) {
83 | let mut first = true;
84 | for e in iter {
85 | if first {
86 | first = false;
87 | } else {
88 | self.put(b' ');
89 | }
90 | e.write(self);
91 | }
92 | }
93 | }
94 |
95 | impl Write for Output<'_> {
96 | fn write(&mut self, buf: &[u8]) -> std::io::Result {
97 | let mut start = 0usize;
98 | let mut rem = buf.len();
99 | while rem > 0 {
100 | let len = (self.buf.len() - self.at).min(rem);
101 | self.buf[self.at..self.at + len].copy_from_slice(&buf[start..start + len]);
102 | self.at += len;
103 | if self.at == self.buf.len() {
104 | self.flush();
105 | }
106 | start += len;
107 | rem -= len;
108 | }
109 | self.maybe_flush();
110 | Ok(buf.len())
111 | }
112 |
113 | fn flush(&mut self) -> std::io::Result<()> {
114 | self.flush();
115 | Ok(())
116 | }
117 | }
118 |
119 | pub trait Writable {
120 | fn write(&self, output: &mut Output);
121 | }
122 |
123 | impl Writable for &str {
124 | fn write(&self, output: &mut Output) {
125 | output.write_all(self.as_bytes()).unwrap();
126 | }
127 | }
128 |
129 | impl Writable for String {
130 | fn write(&self, output: &mut Output) {
131 | output.write_all(self.as_bytes()).unwrap();
132 | }
133 | }
134 |
135 | impl Writable for char {
136 | fn write(&self, output: &mut Output) {
137 | output.put(*self as u8);
138 | }
139 | }
140 |
141 | impl Writable for [T] {
142 | fn write(&self, output: &mut Output) {
143 | output.print_iter_ref(self.iter());
144 | }
145 | }
146 |
147 | impl Writable for [T; N] {
148 | fn write(&self, output: &mut Output) {
149 | output.print_iter_ref(self.iter());
150 | }
151 | }
152 |
153 | impl Writable for &T {
154 | fn write(&self, output: &mut Output) {
155 | T::write(self, output)
156 | }
157 | }
158 |
159 | impl Writable for Vec {
160 | fn write(&self, output: &mut Output) {
161 | self.as_slice().write(output);
162 | }
163 | }
164 |
165 | macro_rules! write_to_string {
166 | ($($t:ident)+) => {$(
167 | impl Writable for $t {
168 | fn write(&self, output: &mut Output) {
169 | self.to_string().write(output);
170 | }
171 | }
172 | )+};
173 | }
174 |
175 | write_to_string!(u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
176 |
177 | macro_rules! tuple_writable {
178 | ($name0:ident $($name:ident: $id:tt )*) => {
179 | impl<$name0: Writable, $($name: Writable,)*> Writable for ($name0, $($name,)*) {
180 | fn write(&self, out: &mut Output) {
181 | self.0.write(out);
182 | $(
183 | out.put(b' ');
184 | self.$id.write(out);
185 | )*
186 | }
187 | }
188 | }
189 | }
190 |
191 | tuple_writable! {T}
192 | tuple_writable! {T U:1}
193 | tuple_writable! {T U:1 V:2}
194 | tuple_writable! {T U:1 V:2 X:3}
195 | tuple_writable! {T U:1 V:2 X:3 Y:4}
196 | tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5}
197 | tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5 A:6}
198 |
199 | impl Writable for Option {
200 | fn write(&self, output: &mut Output) {
201 | match self {
202 | None => (-1).write(output),
203 | Some(t) => t.write(output),
204 | }
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/algo_lib/src/io/input.rs:
--------------------------------------------------------------------------------
1 | use std::fmt::Debug;
2 | use std::io::Read;
3 | use std::str::FromStr;
4 |
5 | pub struct Input<'s> {
6 | input: &'s mut (dyn Read + Send),
7 | buf: Vec,
8 | at: usize,
9 | buf_read: usize,
10 | }
11 |
12 | macro_rules! read_impl {
13 | ($t: ty, $read_name: ident, $read_vec_name: ident) => {
14 | pub fn $read_name(&mut self) -> $t {
15 | self.read()
16 | }
17 |
18 | pub fn $read_vec_name(&mut self, len: usize) -> Vec<$t> {
19 | self.read_vec(len)
20 | }
21 | };
22 |
23 | ($t: ty, $read_name: ident, $read_vec_name: ident, $read_pair_vec_name: ident) => {
24 | read_impl!($t, $read_name, $read_vec_name);
25 |
26 | pub fn $read_pair_vec_name(&mut self, len: usize) -> Vec<($t, $t)> {
27 | self.read_vec(len)
28 | }
29 | };
30 | }
31 |
32 | impl<'s> Input<'s> {
33 | const DEFAULT_BUF_SIZE: usize = 4096;
34 |
35 | pub fn new(input: &'s mut (dyn Read + Send)) -> Self {
36 | Self {
37 | input,
38 | buf: vec![0; Self::DEFAULT_BUF_SIZE],
39 | at: 0,
40 | buf_read: 0,
41 | }
42 | }
43 |
44 | pub fn new_with_size(input: &'s mut (dyn Read + Send), buf_size: usize) -> Self {
45 | Self {
46 | input,
47 | buf: vec![0; buf_size],
48 | at: 0,
49 | buf_read: 0,
50 | }
51 | }
52 |
53 | pub fn get(&mut self) -> Option {
54 | if self.refill_buffer() {
55 | let res = self.buf[self.at];
56 | self.at += 1;
57 | if res == b'\r' {
58 | if self.refill_buffer() && self.buf[self.at] == b'\n' {
59 | self.at += 1;
60 | }
61 | return Some(b'\n');
62 | }
63 | Some(res)
64 | } else {
65 | None
66 | }
67 | }
68 |
69 | pub fn peek(&mut self) -> Option {
70 | if self.refill_buffer() {
71 | let res = self.buf[self.at];
72 | Some(if res == b'\r' { b'\n' } else { res })
73 | } else {
74 | None
75 | }
76 | }
77 |
78 | pub fn skip_whitespace(&mut self) {
79 | while let Some(b) = self.peek() {
80 | if !char::from(b).is_whitespace() {
81 | return;
82 | }
83 | self.get();
84 | }
85 | }
86 |
87 | pub fn next_token(&mut self) -> Option> {
88 | self.skip_whitespace();
89 | let mut res = Vec::new();
90 | while let Some(c) = self.get() {
91 | if char::from(c).is_whitespace() {
92 | break;
93 | }
94 | res.push(c);
95 | }
96 | if res.is_empty() {
97 | None
98 | } else {
99 | Some(res)
100 | }
101 | }
102 |
103 | //noinspection RsSelfConvention
104 | pub fn is_exhausted(&mut self) -> bool {
105 | self.peek().is_none()
106 | }
107 |
108 | //noinspection RsSelfConvention
109 | pub fn is_empty(&mut self) -> bool {
110 | self.skip_whitespace();
111 | self.is_exhausted()
112 | }
113 |
114 | pub fn read(&mut self) -> T {
115 | T::read(self)
116 | }
117 |
118 | pub fn read_vec(&mut self, size: usize) -> Vec {
119 | let mut res = Vec::with_capacity(size);
120 | for _ in 0..size {
121 | res.push(self.read());
122 | }
123 | res
124 | }
125 |
126 | fn read_string(&mut self) -> String {
127 | match self.next_token() {
128 | None => {
129 | panic!("Input exhausted");
130 | }
131 | Some(res) => unsafe { String::from_utf8_unchecked(res) },
132 | }
133 | }
134 |
135 | pub fn read_line(&mut self) -> String {
136 | let mut res = String::new();
137 | while let Some(c) = self.get() {
138 | if c == b'\n' {
139 | break;
140 | }
141 | if c == b'\r' {
142 | if self.peek() == Some(b'\n') {
143 | self.get();
144 | }
145 | break;
146 | }
147 | res.push(c.into());
148 | }
149 | res
150 | }
151 |
152 | fn read_integer(&mut self) -> T
153 | where
154 | ::Err: Debug,
155 | {
156 | let res = self.read_string();
157 | res.parse::().unwrap()
158 | }
159 |
160 |
161 | pub fn read_char(&mut self) -> char {
162 | self.skip_whitespace();
163 | self.get().unwrap().into()
164 | }
165 |
166 | read_impl!(u32, read_unsigned, read_unsigned_vec);
167 | read_impl!(u64, read_u64, read_u64_vec);
168 | read_impl!(usize, read_size, read_size_vec, read_size_pair_vec);
169 | read_impl!(i32, read_int, read_int_vec, read_int_pair_vec);
170 | read_impl!(i64, read_long, read_long_vec, read_long_pair_vec);
171 | read_impl!(i128, read_i128, read_i128_vec);
172 |
173 | fn refill_buffer(&mut self) -> bool {
174 | if self.at == self.buf_read {
175 | self.at = 0;
176 | self.buf_read = self.input.read(&mut self.buf).unwrap();
177 | self.buf_read != 0
178 | } else {
179 | true
180 | }
181 | }
182 | }
183 |
184 | pub trait Readable {
185 | fn read(input: &mut Input) -> Self;
186 | }
187 |
188 | impl Readable for char {
189 | fn read(input: &mut Input) -> Self {
190 | input.read_char()
191 | }
192 | }
193 |
194 | impl Readable for Vec {
195 | fn read(input: &mut Input) -> Self {
196 | let size = input.read();
197 | input.read_vec(size)
198 | }
199 | }
200 |
201 | macro_rules! read_integer {
202 | ($($t:ident)+) => {$(
203 | impl Readable for $t {
204 | fn read(input: &mut Input) -> Self {
205 | input.read_integer()
206 | }
207 | }
208 | )+};
209 | }
210 |
211 | read_integer!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
212 |
213 | macro_rules! tuple_readable {
214 | ($($name:ident)+) => {
215 | impl<$($name: Readable), +> Readable for ($($name,)+) {
216 | fn read(input: &mut Input) -> Self {
217 | ($($name::read(input),)+)
218 | }
219 | }
220 | }
221 | }
222 |
223 | tuple_readable! {T}
224 | tuple_readable! {T U}
225 | tuple_readable! {T U V}
226 | tuple_readable! {T U V X}
227 | tuple_readable! {T U V X Y}
228 | tuple_readable! {T U V X Y Z}
229 | tuple_readable! {T U V X Y Z A}
230 | tuple_readable! {T U V X Y Z A B}
231 | tuple_readable! {T U V X Y Z A B C}
232 | tuple_readable! {T U V X Y Z A B C D}
233 | tuple_readable! {T U V X Y Z A B C D E}
234 | tuple_readable! {T U V X Y Z A B C D E F}
235 |
--------------------------------------------------------------------------------
/templates/tester.rs:
--------------------------------------------------------------------------------
1 | use algo_lib::io::input::Input;
2 | use algo_lib::io::output::Output;
3 |
4 | pub fn check(expected: &mut &[u8], actual: &mut &[u8]) -> Result<(), String> {
5 | let mut expected = Input::new(expected);
6 | let mut actual = Input::new(actual);
7 | let mut token_num = 0usize;
8 | loop {
9 | let expected_token = expected.next_token();
10 | let actual_token = actual.next_token();
11 | if expected_token != actual_token {
12 | if expected_token.is_none() {
13 | return Err(format!("Expected has only {} tokens", token_num));
14 | } else if actual_token.is_none() {
15 | return Err(format!("Actual has only {} tokens", token_num));
16 | } else {
17 | return Err(format!(
18 | "Token #{} differs, expected {}, actual {}",
19 | token_num,
20 | String::from_utf8(expected_token.unwrap()).unwrap(),
21 | String::from_utf8(actual_token.unwrap()).unwrap()
22 | ));
23 | }
24 | }
25 | token_num += 1;
26 | if actual_token.is_none() {
27 | break;
28 | }
29 | }
30 | Ok(())
31 | }
32 |
33 | pub(crate) fn run_tests() -> bool {
34 | let blue = "\x1B[34m";
35 | let red = "\x1B[31m";
36 | let green = "\x1B[32m";
37 | let yellow = "\x1B[33m";
38 | let def = "\x1B[0m";
39 | let time_limit = std::time::Duration::from_millis($TIME_LIMIT);
40 | let mut paths = std::fs::read_dir("./tasks/$TASK/tests/")
41 | .unwrap()
42 | .map(|res| res.unwrap())
43 | .collect::>();
44 | paths.sort_by(|a, b| a.path().cmp(&b.path()));
45 | let mut test_failed = 0usize;
46 | let mut test_total = 0usize;
47 | for path in paths {
48 | let sub_path = path;
49 | if sub_path.file_type().unwrap().is_file() {
50 | let path = sub_path.path();
51 | match path.extension() {
52 | None => {}
53 | Some(extension) => {
54 | if extension.to_str() == Some("in") {
55 | println!("=====================================================");
56 | test_total += 1;
57 | let name = path.file_name().unwrap().to_str().unwrap();
58 | let name = &name[..name.len() - 3];
59 | println!("{}Test {}{}", blue, name, def);
60 | println!("{}Input:{}", blue, def);
61 | println!("{}", std::fs::read_to_string(&path).unwrap());
62 | let expected = match std::fs::read_to_string(
63 | path.parent().unwrap().join(format!("{}.out", name)),
64 | ) {
65 | Ok(res) => Some(res),
66 | Err(_) => None,
67 | };
68 | println!("{}Expected:{}", blue, def);
69 | match &expected {
70 | None => {
71 | println!("{}Not provided{}", yellow, def);
72 | }
73 | Some(expected) => {
74 | println!("{}", expected);
75 | }
76 | }
77 | println!("{}Output:{}", blue, def);
78 | match std::panic::catch_unwind(|| {
79 | let mut file = std::fs::File::open(&path).unwrap();
80 | let started = std::time::Instant::now();
81 | let mut output = Vec::new();
82 | let is_exhausted = crate::run(Input::new(&mut file), Output::new(&mut output));
83 | let res = started.elapsed();
84 | println!("{}", String::from_utf8_lossy(&output));
85 | (output, res, is_exhausted)
86 | }) {
87 | Ok((output, duration, is_exhausted)) => {
88 | println!(
89 | "{}Time elapsed: {:.3}s{}",
90 | blue,
91 | (duration.as_millis() as f64) / 1000.,
92 | def,
93 | );
94 | if !is_exhausted {
95 | println!("{}Input not exhausted{}", red, def);
96 | }
97 | if let Some(expected) = expected {
98 | let mut expected_bytes = expected.as_bytes();
99 | match check(&mut expected_bytes, &mut &output[..]) {
100 | Ok(_) => {}
101 | Err(err) => {
102 | println!(
103 | "{}Verdict: {}Wrong Answer ({}){}",
104 | blue, red, err, def
105 | );
106 | test_failed += 1;
107 | continue;
108 | }
109 | }
110 | }
111 | if duration > time_limit {
112 | test_failed += 1;
113 | println!("{}Verdict: {}Time Limit{}", blue, red, def);
114 | } else {
115 | println!("{}Verdict: {}OK{}", blue, green, def)
116 | }
117 | }
118 | Err(err) => {
119 | test_failed += 1;
120 | match err.downcast::<&str>() {
121 | Ok(as_string) => println!(
122 | "{}Verdict: {}RuntimeError ({:?}){}",
123 | blue, red, as_string, def
124 | ),
125 | Err(err) => println!(
126 | "{}Verdict: {}RuntimeError ({:?}){}",
127 | blue, red, err, def
128 | ),
129 | }
130 | }
131 | }
132 | }
133 | }
134 | }
135 | }
136 | }
137 | if test_failed == 0 {
138 | println!(
139 | "{}All {}{}{} tests passed{}",
140 | blue, green, test_total, blue, def
141 | );
142 | } else {
143 | println!(
144 | "{}{}/{}{} tests failed{}",
145 | red, test_failed, test_total, blue, def
146 | );
147 | }
148 | test_failed == 0
149 | }
150 |
--------------------------------------------------------------------------------
/tasks/a123233/src/tester.rs:
--------------------------------------------------------------------------------
1 | use algo_lib::io::input::Input;
2 | use algo_lib::io::output::Output;
3 |
4 | pub fn check(expected: &mut &[u8], actual: &mut &[u8]) -> Result<(), String> {
5 | let mut expected = Input::new(expected);
6 | let mut actual = Input::new(actual);
7 | let mut token_num = 0usize;
8 | loop {
9 | let expected_token = expected.next_token();
10 | let actual_token = actual.next_token();
11 | if expected_token != actual_token {
12 | if expected_token.is_none() {
13 | return Err(format!("Expected has only {} tokens", token_num));
14 | } else if actual_token.is_none() {
15 | return Err(format!("Actual has only {} tokens", token_num));
16 | } else {
17 | return Err(format!(
18 | "Token #{} differs, expected {}, actual {}",
19 | token_num,
20 | String::from_utf8(expected_token.unwrap()).unwrap(),
21 | String::from_utf8(actual_token.unwrap()).unwrap()
22 | ));
23 | }
24 | }
25 | token_num += 1;
26 | if actual_token.is_none() {
27 | break;
28 | }
29 | }
30 | Ok(())
31 | }
32 |
33 | pub(crate) fn run_tests() -> bool {
34 | let blue = "\x1B[34m";
35 | let red = "\x1B[31m";
36 | let green = "\x1B[32m";
37 | let yellow = "\x1B[33m";
38 | let def = "\x1B[0m";
39 | let time_limit = std::time::Duration::from_millis(2000);
40 | let mut paths = std::fs::read_dir("./tasks/a123233/tests/")
41 | .unwrap()
42 | .map(|res| res.unwrap())
43 | .collect::>();
44 | paths.sort_by(|a, b| a.path().cmp(&b.path()));
45 | let mut test_failed = 0usize;
46 | let mut test_total = 0usize;
47 | for path in paths {
48 | let sub_path = path;
49 | if sub_path.file_type().unwrap().is_file() {
50 | let path = sub_path.path();
51 | match path.extension() {
52 | None => {}
53 | Some(extension) => {
54 | if extension.to_str() == Some("in") {
55 | println!("=====================================================");
56 | test_total += 1;
57 | let name = path.file_name().unwrap().to_str().unwrap();
58 | let name = &name[..name.len() - 3];
59 | println!("{}Test {}{}", blue, name, def);
60 | println!("{}Input:{}", blue, def);
61 | println!("{}", std::fs::read_to_string(&path).unwrap());
62 | let expected = match std::fs::read_to_string(
63 | path.parent().unwrap().join(format!("{}.out", name)),
64 | ) {
65 | Ok(res) => Some(res),
66 | Err(_) => None,
67 | };
68 | println!("{}Expected:{}", blue, def);
69 | match &expected {
70 | None => {
71 | println!("{}Not provided{}", yellow, def);
72 | }
73 | Some(expected) => {
74 | println!("{}", expected);
75 | }
76 | }
77 | println!("{}Output:{}", blue, def);
78 | match std::panic::catch_unwind(|| {
79 | let mut file = std::fs::File::open(&path).unwrap();
80 | let started = std::time::Instant::now();
81 | let mut output = Vec::new();
82 | let is_exhausted = crate::run(Input::new(&mut file), Output::new(&mut output));
83 | let res = started.elapsed();
84 | println!("{}", String::from_utf8_lossy(&output));
85 | (output, res, is_exhausted)
86 | }) {
87 | Ok((output, duration, is_exhausted)) => {
88 | println!(
89 | "{}Time elapsed: {:.3}s{}",
90 | blue,
91 | (duration.as_millis() as f64) / 1000.,
92 | def,
93 | );
94 | if !is_exhausted {
95 | println!("{}Input not exhausted{}", red, def);
96 | }
97 | if let Some(expected) = expected {
98 | let mut expected_bytes = expected.as_bytes();
99 | match check(&mut expected_bytes, &mut &output[..]) {
100 | Ok(_) => {}
101 | Err(err) => {
102 | println!(
103 | "{}Verdict: {}Wrong Answer ({}){}",
104 | blue, red, err, def
105 | );
106 | test_failed += 1;
107 | continue;
108 | }
109 | }
110 | }
111 | if duration > time_limit {
112 | test_failed += 1;
113 | println!("{}Verdict: {}Time Limit{}", blue, red, def);
114 | } else {
115 | println!("{}Verdict: {}OK{}", blue, green, def)
116 | }
117 | }
118 | Err(err) => {
119 | test_failed += 1;
120 | match err.downcast::<&str>() {
121 | Ok(as_string) => println!(
122 | "{}Verdict: {}RuntimeError ({:?}){}",
123 | blue, red, as_string, def
124 | ),
125 | Err(err) => println!(
126 | "{}Verdict: {}RuntimeError ({:?}){}",
127 | blue, red, err, def
128 | ),
129 | }
130 | }
131 | }
132 | }
133 | }
134 | }
135 | }
136 | }
137 | if test_failed == 0 {
138 | println!(
139 | "{}All {}{}{} tests passed{}",
140 | blue, green, test_total, blue, def
141 | );
142 | } else {
143 | println!(
144 | "{}{}/{}{} tests failed{}",
145 | red, test_failed, test_total, blue, def
146 | );
147 | }
148 | test_failed == 0
149 | }
150 |
--------------------------------------------------------------------------------
/main/src/main.rs:
--------------------------------------------------------------------------------
1 | // https://atcoder.jp/contests/abc380/tasks/abc380_a
2 | pub mod solution {
3 | //{"name":"A - 123233","group":"AtCoder - AtCoder Beginner Contest 380","url":"https://atcoder.jp/contests/abc380/tasks/abc380_a","interactive":false,"timeLimit":2000,"tests":[{"input":"123233\n","output":"Yes\n"},{"input":"123234\n","output":"No\n"},{"input":"323132\n","output":"Yes\n"},{"input":"500000\n","output":"No\n"}],"testType":"single","input":{"type":"stdin","fileName":null,"pattern":null},"output":{"type":"stdout","fileName":null,"pattern":null},"languages":{"java":{"taskClass":"A123233"}}}
4 |
5 | use crate::algo_lib::io::input::Input;
6 | use crate::algo_lib::io::output::Output;
7 | use crate::algo_lib::misc::test_type::TaskType;
8 |
9 | use crate::algo_lib::misc::test_type::TestType;
10 |
11 | type PreCalc = ();
12 |
13 | fn solve(input: &mut Input, out: &mut Output, _test_case: usize, _data: &mut PreCalc) {
14 | let mut n = input.read_size();
15 |
16 | let mut d = [0; 6];
17 | for i in 0..6 {
18 | d[i] = n % 10;
19 | n /= 10;
20 | }
21 | d.sort();
22 | out.print_line(if d == [1, 2, 2, 3, 3, 3] {
23 | "Yes"
24 | } else {
25 | "No"
26 | });
27 | }
28 |
29 | pub static TEST_TYPE: TestType = TestType::Single;
30 | pub static TASK_TYPE: TaskType = TaskType::Classic;
31 |
32 | pub(crate) fn run(mut input: Input, mut output: Output) -> bool {
33 | let mut pre_calc = ();
34 |
35 | match TEST_TYPE {
36 | TestType::Single => solve(&mut input, &mut output, 1, &mut pre_calc),
37 | TestType::MultiNumber => {
38 | let t = input.read();
39 | for i in 1..=t {
40 | solve(&mut input, &mut output, i, &mut pre_calc);
41 | }
42 | }
43 | TestType::MultiEof => {
44 | let mut i = 1;
45 | while input.peek().is_some() {
46 | solve(&mut input, &mut output, i, &mut pre_calc);
47 | i += 1;
48 | }
49 | }
50 | }
51 | output.flush();
52 | match TASK_TYPE {
53 | TaskType::Classic => {
54 | input.is_empty()
55 | }
56 | TaskType::Interactive => true,
57 | }
58 | }
59 |
60 |
61 | }
62 | pub mod algo_lib {
63 | #![allow(clippy::too_many_arguments)]
64 | #![allow(clippy::type_complexity)]
65 |
66 | pub mod io {
67 | pub mod input {
68 | use std::fmt::Debug;
69 | use std::io::Read;
70 | use std::str::FromStr;
71 |
72 | pub struct Input<'s> {
73 | input: &'s mut (dyn Read + Send),
74 | buf: Vec,
75 | at: usize,
76 | buf_read: usize,
77 | }
78 |
79 | macro_rules! read_impl {
80 | ($t: ty, $read_name: ident, $read_vec_name: ident) => {
81 | pub fn $read_name(&mut self) -> $t {
82 | self.read()
83 | }
84 |
85 | pub fn $read_vec_name(&mut self, len: usize) -> Vec<$t> {
86 | self.read_vec(len)
87 | }
88 | };
89 |
90 | ($t: ty, $read_name: ident, $read_vec_name: ident, $read_pair_vec_name: ident) => {
91 | read_impl!($t, $read_name, $read_vec_name);
92 |
93 | pub fn $read_pair_vec_name(&mut self, len: usize) -> Vec<($t, $t)> {
94 | self.read_vec(len)
95 | }
96 | };
97 | }
98 |
99 | impl<'s> Input<'s> {
100 | const DEFAULT_BUF_SIZE: usize = 4096;
101 |
102 | pub fn new(input: &'s mut (dyn Read + Send)) -> Self {
103 | Self {
104 | input,
105 | buf: vec![0; Self::DEFAULT_BUF_SIZE],
106 | at: 0,
107 | buf_read: 0,
108 | }
109 | }
110 |
111 | pub fn new_with_size(input: &'s mut (dyn Read + Send), buf_size: usize) -> Self {
112 | Self {
113 | input,
114 | buf: vec![0; buf_size],
115 | at: 0,
116 | buf_read: 0,
117 | }
118 | }
119 |
120 | pub fn get(&mut self) -> Option {
121 | if self.refill_buffer() {
122 | let res = self.buf[self.at];
123 | self.at += 1;
124 | if res == b'\r' {
125 | if self.refill_buffer() && self.buf[self.at] == b'\n' {
126 | self.at += 1;
127 | }
128 | return Some(b'\n');
129 | }
130 | Some(res)
131 | } else {
132 | None
133 | }
134 | }
135 |
136 | pub fn peek(&mut self) -> Option {
137 | if self.refill_buffer() {
138 | let res = self.buf[self.at];
139 | Some(if res == b'\r' { b'\n' } else { res })
140 | } else {
141 | None
142 | }
143 | }
144 |
145 | pub fn skip_whitespace(&mut self) {
146 | while let Some(b) = self.peek() {
147 | if !char::from(b).is_whitespace() {
148 | return;
149 | }
150 | self.get();
151 | }
152 | }
153 |
154 | pub fn next_token(&mut self) -> Option> {
155 | self.skip_whitespace();
156 | let mut res = Vec::new();
157 | while let Some(c) = self.get() {
158 | if char::from(c).is_whitespace() {
159 | break;
160 | }
161 | res.push(c);
162 | }
163 | if res.is_empty() {
164 | None
165 | } else {
166 | Some(res)
167 | }
168 | }
169 |
170 | //noinspection RsSelfConvention
171 | pub fn is_exhausted(&mut self) -> bool {
172 | self.peek().is_none()
173 | }
174 |
175 | //noinspection RsSelfConvention
176 | pub fn is_empty(&mut self) -> bool {
177 | self.skip_whitespace();
178 | self.is_exhausted()
179 | }
180 |
181 | pub fn read(&mut self) -> T {
182 | T::read(self)
183 | }
184 |
185 | pub fn read_vec(&mut self, size: usize) -> Vec {
186 | let mut res = Vec::with_capacity(size);
187 | for _ in 0..size {
188 | res.push(self.read());
189 | }
190 | res
191 | }
192 |
193 | fn read_string(&mut self) -> String {
194 | match self.next_token() {
195 | None => {
196 | panic!("Input exhausted");
197 | }
198 | Some(res) => unsafe { String::from_utf8_unchecked(res) },
199 | }
200 | }
201 |
202 | pub fn read_line(&mut self) -> String {
203 | let mut res = String::new();
204 | while let Some(c) = self.get() {
205 | if c == b'\n' {
206 | break;
207 | }
208 | if c == b'\r' {
209 | if self.peek() == Some(b'\n') {
210 | self.get();
211 | }
212 | break;
213 | }
214 | res.push(c.into());
215 | }
216 | res
217 | }
218 |
219 | fn read_integer(&mut self) -> T
220 | where
221 | ::Err: Debug,
222 | {
223 | let res = self.read_string();
224 | res.parse::().unwrap()
225 | }
226 |
227 |
228 | pub fn read_char(&mut self) -> char {
229 | self.skip_whitespace();
230 | self.get().unwrap().into()
231 | }
232 |
233 | read_impl!(u32, read_unsigned, read_unsigned_vec);
234 | read_impl!(u64, read_u64, read_u64_vec);
235 | read_impl!(usize, read_size, read_size_vec, read_size_pair_vec);
236 | read_impl!(i32, read_int, read_int_vec, read_int_pair_vec);
237 | read_impl!(i64, read_long, read_long_vec, read_long_pair_vec);
238 | read_impl!(i128, read_i128, read_i128_vec);
239 |
240 | fn refill_buffer(&mut self) -> bool {
241 | if self.at == self.buf_read {
242 | self.at = 0;
243 | self.buf_read = self.input.read(&mut self.buf).unwrap();
244 | self.buf_read != 0
245 | } else {
246 | true
247 | }
248 | }
249 | }
250 |
251 | pub trait Readable {
252 | fn read(input: &mut Input) -> Self;
253 | }
254 |
255 | impl Readable for char {
256 | fn read(input: &mut Input) -> Self {
257 | input.read_char()
258 | }
259 | }
260 |
261 | impl Readable for Vec {
262 | fn read(input: &mut Input) -> Self {
263 | let size = input.read();
264 | input.read_vec(size)
265 | }
266 | }
267 |
268 | macro_rules! read_integer {
269 | ($($t:ident)+) => {$(
270 | impl Readable for $t {
271 | fn read(input: &mut Input) -> Self {
272 | input.read_integer()
273 | }
274 | }
275 | )+};
276 | }
277 |
278 | read_integer!(i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize);
279 |
280 | macro_rules! tuple_readable {
281 | ($($name:ident)+) => {
282 | impl<$($name: Readable), +> Readable for ($($name,)+) {
283 | fn read(input: &mut Input) -> Self {
284 | ($($name::read(input),)+)
285 | }
286 | }
287 | }
288 | }
289 |
290 | tuple_readable! {T}
291 | tuple_readable! {T U}
292 | tuple_readable! {T U V}
293 | tuple_readable! {T U V X}
294 | tuple_readable! {T U V X Y}
295 | tuple_readable! {T U V X Y Z}
296 | tuple_readable! {T U V X Y Z A}
297 | tuple_readable! {T U V X Y Z A B}
298 | tuple_readable! {T U V X Y Z A B C}
299 | tuple_readable! {T U V X Y Z A B C D}
300 | tuple_readable! {T U V X Y Z A B C D E}
301 | tuple_readable! {T U V X Y Z A B C D E F}
302 | }
303 | pub mod output {
304 | use std::io::Write;
305 |
306 | pub struct Output<'s> {
307 | output: &'s mut dyn Write,
308 | buf: Vec,
309 | at: usize,
310 | auto_flush: bool,
311 | }
312 |
313 | impl<'s> Output<'s> {
314 | const DEFAULT_BUF_SIZE: usize = 4096;
315 |
316 | pub fn new(output: &'s mut dyn Write) -> Self {
317 | Self {
318 | output,
319 | buf: vec![0; Self::DEFAULT_BUF_SIZE],
320 | at: 0,
321 | auto_flush: false,
322 | }
323 | }
324 |
325 | pub fn new_with_auto_flush(output: &'s mut dyn Write) -> Self {
326 | Self {
327 | output,
328 | buf: vec![0; Self::DEFAULT_BUF_SIZE],
329 | at: 0,
330 | auto_flush: true,
331 | }
332 | }
333 |
334 | pub fn flush(&mut self) {
335 | if self.at != 0 {
336 | self.output.write_all(&self.buf[..self.at]).unwrap();
337 | self.output.flush().unwrap();
338 | self.at = 0;
339 | self.output.flush().expect("Couldn't flush output");
340 | }
341 | }
342 |
343 | pub fn print(&mut self, s: T) {
344 | s.write(self);
345 | }
346 |
347 | pub fn print_line(&mut self, s: T) {
348 | self.print(s);
349 | self.put(b'\n');
350 | }
351 |
352 | pub fn put(&mut self, b: u8) {
353 | self.buf[self.at] = b;
354 | self.at += 1;
355 | if self.at == self.buf.len() {
356 | self.flush();
357 | }
358 | }
359 |
360 | pub fn maybe_flush(&mut self) {
361 | if self.auto_flush {
362 | self.flush();
363 | }
364 | }
365 |
366 | pub fn print_per_line(&mut self, arg: &[T]) {
367 | for i in arg {
368 | i.write(self);
369 | self.put(b'\n');
370 | }
371 | }
372 |
373 | pub fn print_iter>(&mut self, iter: I) {
374 | let mut first = true;
375 | for e in iter {
376 | if first {
377 | first = false;
378 | } else {
379 | self.put(b' ');
380 | }
381 | e.write(self);
382 | }
383 | }
384 |
385 | pub fn print_iter_ref<'a, T: 'a + Writable, I: Iterator
- >(&mut self, iter: I) {
386 | let mut first = true;
387 | for e in iter {
388 | if first {
389 | first = false;
390 | } else {
391 | self.put(b' ');
392 | }
393 | e.write(self);
394 | }
395 | }
396 | }
397 |
398 | impl Write for Output<'_> {
399 | fn write(&mut self, buf: &[u8]) -> std::io::Result {
400 | let mut start = 0usize;
401 | let mut rem = buf.len();
402 | while rem > 0 {
403 | let len = (self.buf.len() - self.at).min(rem);
404 | self.buf[self.at..self.at + len].copy_from_slice(&buf[start..start + len]);
405 | self.at += len;
406 | if self.at == self.buf.len() {
407 | self.flush();
408 | }
409 | start += len;
410 | rem -= len;
411 | }
412 | self.maybe_flush();
413 | Ok(buf.len())
414 | }
415 |
416 | fn flush(&mut self) -> std::io::Result<()> {
417 | self.flush();
418 | Ok(())
419 | }
420 | }
421 |
422 | pub trait Writable {
423 | fn write(&self, output: &mut Output);
424 | }
425 |
426 | impl Writable for &str {
427 | fn write(&self, output: &mut Output) {
428 | output.write_all(self.as_bytes()).unwrap();
429 | }
430 | }
431 |
432 | impl Writable for String {
433 | fn write(&self, output: &mut Output) {
434 | output.write_all(self.as_bytes()).unwrap();
435 | }
436 | }
437 |
438 | impl Writable for char {
439 | fn write(&self, output: &mut Output) {
440 | output.put(*self as u8);
441 | }
442 | }
443 |
444 | impl Writable for [T] {
445 | fn write(&self, output: &mut Output) {
446 | output.print_iter_ref(self.iter());
447 | }
448 | }
449 |
450 | impl Writable for [T; N] {
451 | fn write(&self, output: &mut Output) {
452 | output.print_iter_ref(self.iter());
453 | }
454 | }
455 |
456 | impl Writable for &T {
457 | fn write(&self, output: &mut Output) {
458 | T::write(self, output)
459 | }
460 | }
461 |
462 | impl Writable for Vec {
463 | fn write(&self, output: &mut Output) {
464 | self.as_slice().write(output);
465 | }
466 | }
467 |
468 | macro_rules! write_to_string {
469 | ($($t:ident)+) => {$(
470 | impl Writable for $t {
471 | fn write(&self, output: &mut Output) {
472 | self.to_string().write(output);
473 | }
474 | }
475 | )+};
476 | }
477 |
478 | write_to_string!(u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
479 |
480 | macro_rules! tuple_writable {
481 | ($name0:ident $($name:ident: $id:tt )*) => {
482 | impl<$name0: Writable, $($name: Writable,)*> Writable for ($name0, $($name,)*) {
483 | fn write(&self, out: &mut Output) {
484 | self.0.write(out);
485 | $(
486 | out.put(b' ');
487 | self.$id.write(out);
488 | )*
489 | }
490 | }
491 | }
492 | }
493 |
494 | tuple_writable! {T}
495 | tuple_writable! {T U:1}
496 | tuple_writable! {T U:1 V:2}
497 | tuple_writable! {T U:1 V:2 X:3}
498 | tuple_writable! {T U:1 V:2 X:3 Y:4}
499 | tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5}
500 | tuple_writable! {T U:1 V:2 X:3 Y:4 Z:5 A:6}
501 |
502 | impl Writable for Option {
503 | fn write(&self, output: &mut Output) {
504 | match self {
505 | None => (-1).write(output),
506 | Some(t) => t.write(output),
507 | }
508 | }
509 | }
510 | }
511 | }
512 | pub mod misc {
513 | pub mod test_type {
514 | pub enum TestType {
515 | Single,
516 | MultiNumber,
517 | MultiEof,
518 | }
519 |
520 | pub enum TaskType {
521 | Classic,
522 | Interactive,
523 | }
524 | }
525 | }
526 | }
527 | fn main() {
528 | let mut sin = std::io::stdin();
529 | let input = algo_lib::io::input::Input::new(&mut sin);
530 | let mut stdout = std::io::stdout();
531 | let output = algo_lib::io::output::Output::new(&mut stdout);
532 | crate::solution::run(input, output);
533 | }
534 |
--------------------------------------------------------------------------------