references : boj - https://www.acmicpc.net/user/bubbler
์ ๋ถ์ด ๋ฐฑ์ค์์ cpp ์คํ์ผ io ํ ํ๋ฆฟ์ ๊ตฌํํด๋์ จ๋๋ฐ, ์ ๊ฐ์ ธ๋ค ์ฐ๊ณ ์๋ค. ๊ทธ๋ฌ๋ค๊ฐ ์ด๋ถ๋ถ ์ฝ๋ ๋ณด๊ณ ๊ณต๋ถํ ๋ด์ฉ๋ค์ ์ ๋ฆฌํด๋ดค๋ค.
Intro
use io::*;
pub fn main() {
let stdin = stdin().lock();
let stdout = stdout().lock();
let mut io = IO::new(stdin, stdout);
solve(&mut io);
}
ํ ํ๋ฆฟ์ ํฌํจ๋๋ ๋ฉ์ธํจ์, ์ง์ ์ ์ํ io๋ชจ๋์์ IO์คํธ๋ญํธ๋ฅผ std์ ์ถ๋ ฅ์ ์ ๋ฌํด์ ๋ง๋ค๊ณ ์ค์ ์๊ณ ๋ฆฌ์ฆ ๋ก์ง์ด ๋ค์ด๊ฐ๋ solve ํจ์์ ์ ๋ฌ.
mod IO ๊ตฌ์ฑ
1. struct IO
pub(crate) struct IO<R: BufRead, W: Write> {
ii: I<R>,
oo: BufWriter<W>,
}
impl<R: BufRead, W: Write> IO<R, W> {
pub(crate) fn new(r: R, w: W) -> Self {
Self {
ii: I::new(r),
oo: BufWriter::new(w),
}
}
pub(crate) fn get<T: Fill>(&mut self, exemplar: T) -> Option<T> {
self.ii.get(exemplar)
}
pub(crate) fn put<T: Print>(&mut self, t: T) -> &mut Self {
t.print(&mut self.oo);
self
}
pub(crate) fn nl(&mut self) -> &mut Self {
self.put("\n")
}
}
- ii : Reader๋ฅผ ํ ๋ฒ ๋ ๋ํํ ์คํธ๋ญํธ (ํ์ )
- oo : Writer
- ๊ทธ๋ฆฌ๊ณ ๊ทธ ๋์๋ค์
Fill,Printtrait๋ฅผ ๊ตฌํํด์ผํจ (ํ์ ) - exemplar๋ ํ์ ์ถ๋ก ์ ์ํ ํ ํ๋ฆฟ ๊ฐ
let n: usize = io.get(0usize)?;
2. struct I
pub(crate) struct I<R: BufRead> {
r: R,
line: String,
rem: &'static str,
}
impl<R: BufRead> I<R> {
pub(crate) fn new(r: R) -> Self {
Self {
r,
line: String::new(),
rem: "",
}
}
pub(crate) fn next_line(&mut self) -> Option<()> {
self.line.clear();
(self.r.read_line(&mut self.line).unwrap() > 0)
.then(|| {
self
.rem = unsafe {
(&self.line[..] as *const str).as_ref().unwrap()
};
})
}
pub(crate) fn get<T: Fill>(&mut self, exemplar: T) -> Option<T> {
let mut exemplar = exemplar;
exemplar.fill_from_input(self)?;
Some(exemplar)
}
}
next_line()- Fill ํธ๋ ์ดํธ์์ ์ฌ์ฉ
line์ ๋ฒํผ ์ญํrem์ ํ์ฌ ํ์ฑ ์์น ์ญํ
pub(crate) fn next_line(&mut self) -> Option<()> {
self.line.clear(); // ๋ค์์ค์ ์ฝ๊ธฐ์ํด ํ์ ๋ฒํผ ์ด๊ธฐํ
(self.r.read_line(&mut self.line).unwrap() > 0) // ์ค์ ๋ก ์ฝ์ด๋ค์ธ ๊ฐ์ด ์์ผ๋ฉด
.then(|| {
self
.rem = unsafe { // .rem๋ ๊ฐ์ด ์ด๊ธฐํ๋ฅผ ํด์ฃผ๋๋ฐ
(&self.line[..] as *const str).as_ref().unwrap() // raw ํฌ์ธํฐ๋ก ๋ณํ์ ํด์ค๋ค.
};
})
}
์ raw ํฌ์ธํฐ๋ก ๋ณํ์ ํ์๊น?
์ฌ์ค ์ด๋ถ๋ถ์ด ์ดํด๊ฐ ์๊ฐ๋ ์ฝ๋๋ผ์ ํด๋น ํฌ์คํธ๋ฅผ ์์ฑํ๋ค.
// ์ฌ๊ธฐ์ rem์ ํฌ์ธํฐ๋ก์, line์ ๊ฐ๋ฆฌํค๋ฉฐ ์ง๊ธ ์ด๋๊น์ง ์ฝ์๋์ง๋ฅผ ๋ํ๋ด์ค์ผํ๋ค.
// ์ฆ ๋ก์ง์์ผ๋ก line์ ๋ ํ๋์ ์ฐธ์กฐ ์ญํ ์ด๋ค.
struct I<R: BufRead> {
line: String,
rem: &'??? str, // -> line์ ๊ฐ๋ฆฌํค๋ ํฌ์ธํฐ, ๊ทธ๋ ๋ค๋ฉด ๋ฌ์คํธ ์
์ฅ์์๋ line๋ณด๋ค ์งง์ ์๋ช
์ ์ง์ ํด์ค์ผํจ
}
- ๊ทธ๋์ ์๋์ฒ๋ผ rem์ line์ ์ฐธ์กฐ๋ก ์ฐ๊ธฐ ์ํด์ ๋ผ์ดํํ์์ ์๋ ค์ค์ผ ์ปดํ์ผ ํด์ค๋ค.
struct I<'a, R: BufRead> {
line: String,
rem: &'a str, // rem์ line๋ณด๋ค ์งง์ ๋ผ์ดํํ์๊ณผ ํ๋์ ๋ฌธ์์ด์ ๋ํ ๋ ์ฐธ์กฐ๊ฐ ํ์ํ ์ํฉ์ ํด๊ฒฐํด์ผํ๋ค.
}
- ๋ฌธ์ ๋ ๋ฌ์คํธ์ ๋ผ์ดํํ์์ ์งํค๋ฉฐ ์์ ์ฝ๋์ฒ๋ผ ํ๋ ค๋ฉด
'a๋ฅผ ๊ตฌ์กฐ์ฒด ์ธ๋ถ์์ ๊ฒฐ์ ํด์ผ ํ๋ค - next_line() ํจ์ ๋ด์์
&self.line์ ๋ผ์ดํํ์์ ํจ์ ๋ฒ์์ธ๋ฐ ์ค์ rem์ ๊ตฌ์กฐ์ฒด๊ฐ ์ด์์๋ ๋์ ์ ํจํด์ผ ํ๋ค.
๊ทธ๋์ ๊ทธ๋ฅ raw pointer ์ฌ์ฉํด์
self.rem = unsafe {
(&self.line[..] as *const str).as_ref().unwrap()
};
&self.line[..]โ&str(์ผ๋ฐ์ ์ธ ์ฐธ์กฐ)as *const strโ raw ํฌ์ธํฐ๋ก ๋ณํ (๋ผ์ดํํ์ ์ ๋ณด ์ ๊ฑฐ).as_ref().unwrap()โ ๋ค์ ์ฐธ์กฐ๋ก ๋ณํํ๋'static๋ผ์ดํํ์์ผ๋ก
์ด๋ ๊ฒ ์์ ํ ๊ตฌํ์ ํ๋ฉด ํ ์๋ ์๋๋ฐ, ํด๋ก๋ํํ ๋ฌผ์ด๋ณด๋ ์ด๋ ๊ฒ๋๋ฉด ๋งค๋ฒ ์ฌ๋ผ์ด์ฑ ์ฐ์ฐ๊ณผ ๋ฐ์ด๋ ์ฒดํฌ ์ค๋ฒํค๋๊ฐ ๋ฐ์ํ๊ณ ps์์๋ ๋ฌด์ํ ์ ์์ ์ ๋์ผ ๊ฒ ์ด๋ผ๊ณ ํ๋ค.
struct I<R: BufRead> {
r: R,
line: String,
pos: usize,
}
impl<R: BufRead> I<R> {
fn remaining(&self) -> &str {
&self.line[self.pos..]
}
fn advance(&mut self, len: usize) {
self.pos += len;
}
}
๊ทธ๋ฆฌ๊ณ line.clear()๋ฅผ ์์ ๋๊ณ ๋งค๋ฒ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ์์ง๊น์ง๋ ์ถฉ๋ถํ ์์ ํ๊ณ ์ฌ์ฉ์ฉ๋์๋ ์๋ง๋ ๋ฐฉ์
3 trail Fill
๊ทธ๋ฆฌ๊ณ ์๋์ฒ๋ผ ์ค์ ๋ก ์ฝ์ด๋ธ๋ค.
pub(crate) trait Fill {
fn fill_from_input<R: BufRead>(&mut self, i: &mut I<R>) -> Option<()>;
}
fn ws(c: char) -> bool {
c <= ' '
}
impl Fill for String {
fn fill_from_input<R: BufRead>(&mut self, i: &mut I<R>) -> Option<()> {
// ๊ณต๋ฐฑ ์คํต
i.rem = i.rem.trim_start_matches(ws);
// ๋น์ด์์ผ๋ฉด ์ค๋ฐ๊ฟ์ ์คํต
while i.rem.is_empty() {
i.next_line()?;
i.rem = i.rem.trim_start_matches(ws);
}
// ํ ํฐ ํ๋ ๋ฝ๊ณ
let tok = i.rem.split(ws).next().unwrap();
// ํฌ์ธํฐ ๋ฐ์ด์ฃผ๊ณ
i.rem = &i.rem[tok.len()..];
*self = tok.to_string();
Some(())
}
}
impl Fill for Vec<u8> {
fn fill_from_input<R: BufRead>(&mut self, i: &mut I<R>) -> Option<()> {
i.rem = i.rem.trim_start_matches(ws);
while i.rem.is_empty() {
i.next_line()?;
i.rem = i.rem.trim_start_matches(ws);
}
let tok = i.rem.split(ws).next().unwrap();
i.rem = &i.rem[tok.len()..];
self.extend_from_slice(tok.as_bytes());
Some(())
}
}
// iter๋ก ์ฒ๋ฆฌ
impl<T: Fill> Fill for Vec<T> {
fn fill_from_input<R: BufRead>(&mut self, i: &mut I<R>) -> Option<()> {
for ii in self.iter_mut() {
ii.fill_from_input(i)?;
}
Some(())
}
}
pub(crate) fn get<T: Fill>(&mut self, exemplar: T) -> Option<T> {
let mut exemplar = exemplar;
exemplar.fill_from_input(self)?;
Some(exemplar)
}