Hello everyone, I always liked to participate in a contest with rust, but its lack of a good input/output system always discouraged me from doing so. For that reason, I've prepared a rust Scanner
struct (or class
if you're a Java dev) which its interface is like Java's scanner and it functions like C++'s cin
. Hope it comes in handy in your contests and you experience a contest with a new programming language:
use std::io;
use std::collections::VecDeque;
struct Scanner {
buffer: VecDeque<char>
}
#[allow(dead_code)]
impl Scanner {
fn new() -> Self {
Self {
buffer: VecDeque::new()
}
}
fn _fill_buffer(&mut self) {
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
self.buffer = input.trim().chars().collect::<VecDeque<char>>();
self.buffer.push_back('\n');
}
fn is_empty(&mut self) -> bool {
self.buffer.is_empty()
}
fn _autofill(&mut self) {
if self.buffer.is_empty() {
self._fill_buffer();
}
}
fn _get_char_unchecked(&mut self) -> char {
self._autofill();
self.buffer.pop_front().unwrap()
}
fn _is_white(&mut self, c: char) -> bool {
c == ' ' || c == '\n' || c == '\r' || c == '\t'
}
fn _ignore_white(&mut self) {
loop {
self._autofill();
let c = self._get_char_unchecked();
if !self._is_white(c) {
self.buffer.push_front(c);
break;
}
}
}
fn next_char(&mut self) -> char {
loop {
let c = self._get_char_unchecked();
if !self._is_white(c) {
return c;
}
}
}
fn next_line(&mut self) -> String {
let mut res = String::new();
loop {
self._autofill();
let c = self._get_char_unchecked();
if c == '\n' {
break;
}
res.push(c);
}
res
}
fn next_token(&mut self) -> String {
let mut res = String::new();
loop {
self._autofill();
self._ignore_white();
if !self.buffer.is_empty() {
break;
}
}
loop {
self._autofill();
let c = self._get_char_unchecked();
if self._is_white(c) {
break;
}
res.push(c);
}
res
}
fn _is_numeric(&mut self, c: char) -> bool {
c >= '0' && c <= '9'
}
fn _is_num_start(&mut self, c: char) -> bool {
self._is_numeric(c) || c == '-' || c == '+'
}
fn next_i64(&mut self) -> i64 {
let mut res: i64 = 0;
let mut neg = 1;
let mut num_started: bool = false;
loop {
self._autofill();
if !num_started {
self._ignore_white();
}
let mut c = self._get_char_unchecked();
if !self._is_num_start(c) {
if num_started {
self.buffer.push_front(c);
break;
}
continue;
}
if num_started && !self._is_numeric(c) {
self.buffer.push_front(c);
break;
}
if !num_started {
if c == '0' {
return 0;
}
if c == '-' {
neg = -1;
c = self._get_char_unchecked();
}
num_started = true;
}
if self._is_numeric(c) {
res = 10 * res + (c as u8 - '0' as u8) as i64;
}
}
res * neg
}
fn next_i32(&mut self) -> i32 {
self.next_i64() as i32
}
fn next_u64(&mut self) -> u64 {
self.next_i64() as u64
}
fn next_u32(&mut self) -> u32 {
self.next_i64() as u32
}
fn next_f64(&mut self) -> f64 {
let mut string_form: String = String::new();
loop {
self._autofill();
self._ignore_white();
let mut c = self._get_char_unchecked();
if self._is_num_start(c) || c == '.' {
if c == '.' {
string_form.push('0');
}
string_form.push(c);
break;
}
}
loop {
self._autofill();
let c = self._get_char_unchecked();
if !self._is_numeric(c) && c != '.' {
break;
}
string_form.push(c);
}
string_form.parse::<f64>().unwrap()
}
fn next_f32(&mut self) -> f32 {
self.next_f64() as f32
}
fn push_buffer(&mut self, c: char) {
self.buffer.push_front(c);
}
fn push_str(&mut self, s: &str) {
for c in s.chars().rev() {
self.buffer.push_front(c);
}
}
fn push_string(&mut self, s: String) {
for c in s.chars().rev() {
self.buffer.push_front(c);
}
}
fn set_buffer(&mut self, s: String) {
self.buffer = s.chars().collect::<VecDeque<char>>();
}
}
static mut SINGLETON_SCANNER: Option<Scanner> = None;
fn get_scanner() -> &'static mut Scanner {
unsafe {
if SINGLETON_SCANNER.is_none() {
SINGLETON_SCANNER = Some(Scanner::new());
}
SINGLETON_SCANNER.as_mut().unwrap()
}
}
fn solve() {
// Solve each test case here...
}
fn main() {
let scanner = get_scanner();
// let t = 1; // Uncomment if there's no test cases
let t = scanner.next_i32(); // Uncomment if there's test cases.
for _ in 0..t {
solve();
}
}