├── 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 | --------------------------------------------------------------------------------