competitive-hpp 0.10.23

Competitive Programming Library for AtCoder with Rust
Documentation
use std::io::Write;

macro_rules! macro_map {
    ($mcr:ident, $($e:ty),*) => {
        $(
            $mcr!($e);
        )*
    };
}

#[macro_export]
macro_rules! echo {
    ($($e:expr),*) => {
        ($($e),*).echo(&mut std::io::stdout()).unwrap();
        println!();
    };
}

pub trait Echo {
    fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error>;
}

impl<T: Echo> Echo for Vec<T> {
    fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
        for (i, value) in self.iter().enumerate() {
            if i > 0 {
                write!(w, " ")?;
            }
            value.echo(w)?;
        }
        Ok(())
    }
}

pub struct Mat<T>(pub Vec<Vec<T>>);

impl<T: Echo> Echo for Mat<T> {
    fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
        for i in 0..self.0.len() {
            if i > 0 {
                writeln!(w)?;
            }
            self.0[i].echo(w)?;
        }
        Ok(())
    }
}

pub struct MatS(pub Vec<Vec<char>>);

impl Echo for MatS {
    fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
        for i in 0..self.0.len() {
            if i > 0 {
                writeln!(w)?;
            }
            for j in 0..self.0[i].len() {
                write!(w, "{}", self.0[i][j])?;
            }
        }
        Ok(())
    }
}

macro_rules! impl_tuple_for_echo {
    ($v0:ident: $t0:ident $(, $v:ident: $t:ident)*) => {
        impl< $t0 : Echo $(, $t : Echo)* > Echo for ($t0, $($t),*) {
            fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
                let (v0, $($v),*) = self;
                v0.echo(w)?;
                $(
                    write!(w, " ")?;
                    $v.echo(w)?;
                )*
                Ok(())
            }
        }
    };
}

macro_rules! tuple_echo_impls {
    ($v0:ident: $t0:ident $(, $v:ident: $t:ident)*) => {
        tuple_echo_impls!($($v: $t),*);
        impl_tuple_for_echo!($v0: $t0 $(, $v: $t)*);
    };
    () => {};
}

tuple_echo_impls!(
    t7: T7,
    t6: T6,
    t5: T5,
    t4: T4,
    t3: T3,
    t2: T2,
    t1: T1,
    t0: T0
);

macro_rules! impl_echo {
    ($t:ty) => {
        impl Echo for $t {
            fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
                write!(w, "{}", self)
            }
        }
    };
}

macro_rules! impl_echo_float {
    ($t:ty) => {
        impl Echo for $t {
            fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
                write!(w, "{:.12}", self)
            }
        }
    };
}

macro_map!(impl_echo, i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
macro_map!(impl_echo, char, &str, String);
macro_map!(impl_echo_float, f32, f64);

#[cfg(test)]
mod test {
    use super::*;
    #[allow(clippy::approx_constant)]
    #[test]
    fn test_echo() {
        fn echo_str(v: impl Echo) -> String {
            let mut buf = vec![];
            v.echo(&mut buf).unwrap();
            String::from_utf8(buf).unwrap()
        }

        assert_eq!(echo_str(1_i32), "1");
        assert_eq!(echo_str((1, 2, 3)), "1 2 3");
        assert_eq!(echo_str((1, 3.14, "hello")), "1 3.140000000000 hello");
        assert_eq!(echo_str(vec![1, 2, 3]), "1 2 3");

        let m = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
        assert_eq!(echo_str(Mat(m)), "1 2 3\n4 5 6\n7 8 9");

        let m = vec![
            vec!['a', 'b', 'c'],
            vec!['d', 'e', 'f'],
            vec!['g', 'h', 'i'],
        ];
        assert_eq!(echo_str(MatS(m)), "abc\ndef\nghi");
    }
}