1use std::fs::File;
2use std::io::{self, BufRead, BufReader};
3pub fn read_string() -> String {
8 let mut input = String::new();
9 io::stdin().read_line(&mut input).expect("Failed to read line");
10 input.trim().to_string()
11}
12
13pub fn read_charvec() -> Vec<char> {
14 let mut input = String::new();
15 io::stdin().read_line(&mut input).expect("Failed to read line");
16 input.trim().chars().collect()
17}
18
19pub fn read_string_notrim() -> String {
20 let mut input = String::new();
21 io::stdin().read_line(&mut input).expect("Failed to read line");
22 input.to_string()
23}
24
25pub fn read_u32() -> u32 {
26 let mut input = String::new();
27 io::stdin().read_line(&mut input).expect("Failed to read line");
28 input = input.trim_start().to_string();
29
30 if input.starts_with('-') {
31 input = input[1..].to_string();
32 }
33
34 let number_str = match input.trim().find('.') {
35 Some(dot_index) => &input[..dot_index],
36 None => input.trim(),
37 };
38
39 if number_str.is_empty() {
40 return 0;
41 }
42
43 number_str.parse().expect("Could not parse a valid unsigned 32-bit integer.")
44}
45
46pub fn read_i32() -> i32 {
47 let mut input = String::new();
48 io::stdin().read_line(&mut input).expect("Failed to read line");
49
50 let number_str = match input.trim().find('.') {
51 Some(dot_index) => &input[..dot_index],
52 None => input.trim(),
53 };
54
55 if number_str.is_empty() || number_str == "-" {
56 return 0;
57 }
58
59 number_str.parse().expect("Could not parse a valid 32-bit integer.")
60}
61
62pub fn read_u64() -> u64 {
63 let mut input = String::new();
64 io::stdin().read_line(&mut input).expect("Failed to read line");
65 input = input.trim_start().to_string();
66
67 if input.starts_with('-') {
68 input = input[1..].to_string();
69 }
70
71 let number_str = match input.trim().find('.') {
72 Some(dot_index) => &input[..dot_index],
73 None => input.trim(),
74 };
75
76 if number_str.is_empty() {
77 return 0;
78 }
79
80 number_str.parse().expect("Could not parse a valid unsigned 64-bit integer.")
81}
82
83pub fn read_i64() -> i64 {
84 let mut input = String::new();
85 io::stdin().read_line(&mut input).expect("Failed to read line");
86
87 let number_str = match input.trim().find('.') {
88 Some(dot_index) => &input[..dot_index],
89 None => input.trim(),
90 };
91
92 if number_str.is_empty() || number_str == "-" {
93 return 0;
94 }
95
96 number_str.parse().expect("Could not parse a valid 64-bit integer.")
97}
98
99pub fn read_f32() -> f32 {
100 let mut input = String::new();
101 io::stdin().read_line(&mut input).expect("Failed to read line");
102 input.trim().parse().expect("Could not parse a valid floating-point number.")
103}
104
105pub fn read_f64() -> f64 {
106 let mut input = String::new();
107 io::stdin().read_line(&mut input).expect("Failed to read line");
108 input.trim().parse().expect("Could not parse a valid floating-point number.")
109}
110
111pub fn read_u8() -> u8 {
112 let mut input = String::new();
113 io::stdin().read_line(&mut input).expect("Failed to read line");
114 input = input.trim_start().to_string();
115
116 if input.starts_with('-') {
117 input = input[1..].to_string();
118 }
119
120 let number_str = match input.trim().find('.') {
121 Some(dot_index) => &input[..dot_index],
122 None => input.trim(),
123 };
124
125 number_str.parse().expect("Could not parse a valid unsigned 8-bit integer.")
126}
127
128pub fn read_char() -> char {
129 let mut input = String::new();
130 io::stdin().read_line(&mut input).expect("Failed to read line");
131 input.chars().next().expect("Could not parse a valid character.")
132}
133
134pub struct LineReader<> {
137 reader: BufReader<File>,
138 current_line: String,
139}
140
141impl<'a> LineReader<> {
142 pub fn new(file_path: &str) -> io::Result<Self> {
143 let file = File::open(file_path)?;
144 let reader = BufReader::new(file);
145 let current_line = String::new();
146
147 Ok(Self {
148 reader,
149 current_line,
150 })
151 }
152
153 pub fn get_next_line(&mut self) -> io::Result<Option<String>> {
154 self.current_line.clear();
155 match self.reader.read_line(&mut self.current_line)? {
156 0 => Ok(None), _ => Ok(Some(self.current_line.clone())),
158 }
159 }
160
161 pub fn get_current_line(&self) -> &str {
162 &self.current_line
163 }
164
165 pub fn get_file_next_string(&mut self) -> io::Result<Option<String>> { self.get_next_line()
167 }
168
169 pub fn get_file_next_char(&mut self) -> io::Result<Option<char>> {
170 match self.get_next_line()? {
171 Some(line) => Ok(line.chars().next()),
172 None => Ok(None),
173 }
174 }
175
176 pub fn get_file_next_uint(&mut self) -> io::Result<Option<u64>> { match self.get_next_line()? {
178 Some(line) => {
179 let input = line.trim();
180 let number_str = match input.find('.') {
181 Some(dot_index) => &input[..dot_index],
182 None => input,
183 };
184
185 if number_str.is_empty() {
186 return Ok(Some(0));
187 }
188
189 match number_str.parse::<u64>() {
190 Ok(num) => Ok(Some(num)),
191 Err(_) => Ok(None),
192 }
193 }
194 None => Ok(None),
195 }
196 }
197
198 pub fn get_file_next_int(&mut self) -> io::Result<Option<i64>> { match self.get_next_line()? {
200 Some(line) => {
201 let input = line.trim();
202 let number_str = match input.find('.') {
203 Some(dot_index) => &input[..dot_index],
204 None => input,
205 };
206
207 if number_str.is_empty() {
208 return Ok(Some(0));
209 }
210
211 match number_str.parse::<i64>() {
212 Ok(num) => Ok(Some(num)),
213 Err(_) => Ok(None),
214 }
215 }
216 None => Ok(None),
217 }
218 }
219
220 pub fn get_file_next_unsigned_float(&mut self) -> io::Result<Option<f64>> { match self.get_next_line()? {
222 Some(line) => {
223 let input = line.trim();
224 let number_str = match input.find('.') {
225 Some(dot_index) => &input[..dot_index],
226 None => input,
227 };
228
229 if number_str.is_empty() {
230 return Ok(Some(0.0));
231 }
232
233 match number_str.parse::<f64>() {
234 Ok(num) => Ok(Some(num)),
235 Err(_) => Ok(None),
236 }
237 }
238 None => Ok(None),
239 }
240 }
241}