artinz's blog

By artinz, history, 10 hours ago, In English

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();
    }
}
  • Vote: I like it
  • +4
  • Vote: I do not like it