competitive_hpp/
echo.rs

1use std::io::Write;
2
3macro_rules! macro_map {
4    ($mcr:ident, $($e:ty),*) => {
5        $(
6            $mcr!($e);
7        )*
8    };
9}
10
11#[macro_export]
12macro_rules! echo {
13    ($($e:expr),*) => {
14        ($($e),*).echo(&mut std::io::stdout()).unwrap();
15        println!();
16    };
17}
18
19pub trait Echo {
20    fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error>;
21}
22
23impl<T: Echo> Echo for Vec<T> {
24    fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
25        for (i, value) in self.iter().enumerate() {
26            if i > 0 {
27                write!(w, " ")?;
28            }
29            value.echo(w)?;
30        }
31        Ok(())
32    }
33}
34
35pub struct Mat<T>(pub Vec<Vec<T>>);
36
37impl<T: Echo> Echo for Mat<T> {
38    fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
39        for i in 0..self.0.len() {
40            if i > 0 {
41                writeln!(w)?;
42            }
43            self.0[i].echo(w)?;
44        }
45        Ok(())
46    }
47}
48
49pub struct MatS(pub Vec<Vec<char>>);
50
51impl Echo for MatS {
52    fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
53        for i in 0..self.0.len() {
54            if i > 0 {
55                writeln!(w)?;
56            }
57            for j in 0..self.0[i].len() {
58                write!(w, "{}", self.0[i][j])?;
59            }
60        }
61        Ok(())
62    }
63}
64
65macro_rules! impl_tuple_for_echo {
66    ($v0:ident: $t0:ident $(, $v:ident: $t:ident)*) => {
67        impl< $t0 : Echo $(, $t : Echo)* > Echo for ($t0, $($t),*) {
68            fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
69                let (v0, $($v),*) = self;
70                v0.echo(w)?;
71                $(
72                    write!(w, " ")?;
73                    $v.echo(w)?;
74                )*
75                Ok(())
76            }
77        }
78    };
79}
80
81macro_rules! tuple_echo_impls {
82    ($v0:ident: $t0:ident $(, $v:ident: $t:ident)*) => {
83        tuple_echo_impls!($($v: $t),*);
84        impl_tuple_for_echo!($v0: $t0 $(, $v: $t)*);
85    };
86    () => {};
87}
88
89tuple_echo_impls!(
90    t7: T7,
91    t6: T6,
92    t5: T5,
93    t4: T4,
94    t3: T3,
95    t2: T2,
96    t1: T1,
97    t0: T0
98);
99
100macro_rules! impl_echo {
101    ($t:ty) => {
102        impl Echo for $t {
103            fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
104                write!(w, "{}", self)
105            }
106        }
107    };
108}
109
110macro_rules! impl_echo_float {
111    ($t:ty) => {
112        impl Echo for $t {
113            fn echo(&self, w: &mut impl Write) -> Result<(), std::io::Error> {
114                write!(w, "{:.12}", self)
115            }
116        }
117    };
118}
119
120macro_map!(impl_echo, i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
121macro_map!(impl_echo, char, &str, String);
122macro_map!(impl_echo_float, f32, f64);
123
124#[cfg(test)]
125mod test {
126    use super::*;
127    #[allow(clippy::approx_constant)]
128    #[test]
129    fn test_echo() {
130        fn echo_str(v: impl Echo) -> String {
131            let mut buf = vec![];
132            v.echo(&mut buf).unwrap();
133            String::from_utf8(buf).unwrap()
134        }
135
136        assert_eq!(echo_str(1_i32), "1");
137        assert_eq!(echo_str((1, 2, 3)), "1 2 3");
138        assert_eq!(echo_str((1, 3.14, "hello")), "1 3.140000000000 hello");
139        assert_eq!(echo_str(vec![1, 2, 3]), "1 2 3");
140
141        let m = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
142        assert_eq!(echo_str(Mat(m)), "1 2 3\n4 5 6\n7 8 9");
143
144        let m = vec![
145            vec!['a', 'b', 'c'],
146            vec!['d', 'e', 'f'],
147            vec!['g', 'h', 'i'],
148        ];
149        assert_eq!(echo_str(MatS(m)), "abc\ndef\nghi");
150    }
151}