comp_io/
lib.rs

1//! # Comp IO
2//!
3//! `comp_io` is a collection of utilities centered around the `Reader` struct
4//! to make competitive programming easier to write
5
6use std::io::{self, Read};
7
8/// Reads data from stdin in an optimized manner
9///
10/// Limitations: doesn't skip whitespace. Assumes that input data is sanitized (each number is separated by exactly 1 character)
11/// This allows for faster reading of data, because in most competitive programming scenarios, the input data is already provided
12/// in such a way
13///
14/// # Example:
15///
16/// ```no_run
17/// let mut reader = comp_io::Reader::new();
18///
19/// // Read an i32:
20/// let a: i32 = reader.next_i32().unwrap();
21///
22/// // Read a pair of i32s:
23/// let (b, c): (i32, i32) = reader.next_pair().unwrap();
24///
25/// // Read an f64
26/// let d: f64 = reader.next_f64().unwrap();
27/// ```
28pub struct Reader {
29    buffer: Vec<u8>,
30    index: usize,
31    len: usize,
32}
33//        ___      _________________
34//       /  .\    /                 \
35//      /  =__|  <  Walrus Approved.|
36// hjm /    ||    \_________________/
37impl Iterator for Reader {
38    type Item = u8;
39
40    #[cfg(not(test))]
41    fn next(&mut self) -> Option<Self::Item> {
42        // If at end of buffer
43        if self.index >= self.len {
44            if self.len < 400_000 {
45                return None;
46            }
47            // Try to read from stdin
48            self.buffer.clear(); // necessary?
49            self.len = io::stdin()
50                .lock()
51                .take(400_000)
52                .read_to_end(&mut self.buffer)
53                .ok()?;
54            self.index = 0;
55        }
56        let n = self.buffer[self.index];
57        self.index += 1;
58        Some(n)
59    }
60
61    #[cfg(test)]
62    fn next(&mut self) -> Option<Self::Item> {
63        // If at end of buffer
64        if self.index >= self.len {
65            return None;
66        }
67        let n = self.buffer[self.index];
68        self.index += 1;
69        Some(n)
70    }
71}
72
73impl Reader {
74    /// Instantiates a new reader
75    ///
76    /// # Example:
77    ///
78    /// ```
79    /// let mut reader = comp_io::Reader::new();
80    /// ```
81    pub fn new() -> Self {
82        Reader {
83            buffer: Vec::<u8>::with_capacity(400_000),
84            index: usize::MAX,
85            len: usize::MAX,
86        }
87    }
88
89    /// Useful for testing reader without requiring access to stdin
90    ///
91    /// Note: Best with `cargo test`, otherwise still needs stdin
92    ///
93    /// # Example:
94    ///
95    /// ```
96    /// let mut reader = comp_io::Reader::from_str("12 43\n-42");
97    /// ```
98    pub fn from_str(input: &str) -> Self {
99        Reader {
100            buffer: input.as_bytes().to_vec(),
101            index: 0,
102            len: input.len(),
103        }
104    }
105
106    fn read_i32(&mut self) -> Option<(i32, i32)> {
107        // let (mut r, mut val, neg) = (0, 48, self.next()? == b'-');
108        // self.index -= if neg {0} else {1};
109
110        let mut r = 0;
111        let (mut val, neg) = match self.next()? {
112            v @ b'0'..=b'9' => (v as i32, false), // could also move to the end with no ifs, don't know which is better
113            b'-' => (48, true),
114            b'+' => (48, false),
115            _ => return None, // Unexpected character
116        };
117
118        while val >= b'0' as i32 && val <= b'9' as i32 {
119            r = r * 10 + val - 48;
120
121            val = match self.next() {
122                Some(a) => a as i32,
123                None => break,
124            };
125        }
126        Some((if neg { -r } else { r }, val))
127    }
128
129    /// Reads the next u32 from stdin
130    pub fn next_u32(&mut self) -> Option<u32> {
131        Some(self.read_i32()?.0.unsigned_abs())
132    }
133
134    /// Reads the next usize from stdin
135    pub fn next_usize(&mut self) -> Option<usize> {
136        Some(self.read_i32()?.0.unsigned_abs() as usize)
137    }
138
139    /// Reads the next i32 from stdin
140    pub fn next_i32(&mut self) -> Option<i32> {
141        Some(self.read_i32()?.0)
142    }
143
144    /// Reads the next char from stdin
145    pub fn next_char(&mut self) -> Option<char> {
146        Some(self.next()? as char)
147    }
148
149    /// Reads the next pair of i32s from stdin
150    pub fn next_pair(&mut self) -> Option<(i32, i32)> {
151        Some((self.read_i32()?.0, self.read_i32()?.0))
152    }
153
154    /// Reads the next f64 from stdin
155    pub fn next_f64(&mut self) -> Option<f64> {
156        let (base, latest) = self.read_i32()?;
157        let base: f64 = base as f64;
158        if latest != b'.' as i32 { // number doesn't have a period
159            return Some(base);
160        }
161        let (mut dec, mut val, mut ten) = (0.0, 48, 1.0);
162        while val >= b'0' && val <= b'9' {
163            dec += ((val - b'0') as f64) * ten;
164            ten *= 0.1;
165            val = match self.next() {
166                Some(a) => a,
167                _ => break,
168            };
169        }
170        Some(base + dec.copysign(base))
171    }
172}
173
174#[cfg(test)]
175mod tests {
176    use super::*;
177
178    #[test]
179    fn test_reader_from_str() {
180        let reader = Reader::from_str("-4.1");
181
182        assert_eq!(reader.buffer, vec![45, 52, 46, 49]);
183        assert_eq!(reader.index, 0);
184        assert_eq!(reader.len, 4);
185    }
186
187    #[test]
188    fn test_next_f64() {
189        let mut reader = Reader::from_str("-4 45 -754.3 32. 45");
190        assert_eq!(reader.next_f64().unwrap(), -4.);
191        assert_eq!(reader.next_f64().unwrap(), 45.);
192        assert_eq!(reader.next_f64().unwrap(), -754.3);
193        assert_eq!(reader.next_f64().unwrap(), 32.);
194        assert_eq!(reader.next_f64().unwrap(), 45.);
195    }
196
197    #[test]
198    fn test_next_char() {
199        let mut reader = Reader::from_str("ab cd");
200        assert_eq!(reader.next_char().unwrap(), 'a');
201        assert_eq!(reader.next_char().unwrap(), 'b');
202        assert_eq!(reader.next_char().unwrap(), ' ');
203        assert_eq!(reader.next_char().unwrap(), 'c');
204        assert_eq!(reader.next_char().unwrap(), 'd');
205    }
206
207    #[test]
208    fn test_next_pair() {
209        let mut reader = Reader::from_str("23 32\n12 -34 57 97\n-12 3");
210        assert_eq!(reader.next_pair().unwrap(), (23, 32));
211        assert_eq!(reader.next_pair().unwrap(), (12, -34));
212        assert_eq!(reader.next_pair().unwrap(), (57, 97));
213        assert_eq!(reader.next_pair().unwrap(), (-12, 3));
214    }
215
216    #[test]
217    fn test_next_usize() {
218        let mut reader = Reader::from_str("23 32\n12\n34");
219        assert_eq!(reader.next_usize().unwrap(), 23);
220        assert_eq!(reader.next_usize().unwrap(), 32);
221        assert_eq!(reader.next_usize().unwrap(), 12);
222        assert_eq!(reader.next_usize().unwrap(), 34);
223    }
224
225    #[test]
226    fn test_long_float() {
227        let mut reader = Reader::from_str("4.323580432456786");
228        assert_eq!(reader.next_f64().unwrap(), 4.323580432456786);
229    }
230}