1pub mod binary_search;
2pub mod dijkstra;
3pub mod dir;
4pub mod iter;
5pub mod matrix;
6pub mod option_min_max;
7pub mod point;
8pub mod trie;
9
10use std::{
11 fmt,
12 fs::{File, read_to_string},
13 io::BufWriter,
14 ops,
15 str::FromStr,
16};
17
18use num_traits::Zero;
19
20#[macro_export]
21macro_rules! printwriteln {
22 ($writer:expr, $fmt:literal) => {
23 {
24 println!($fmt);
25 writeln!($writer, $fmt)
26 }
27 };
28 ($writer:expr, $fmt:literal, $($args:expr),+) => {
29 {
30 println!($fmt, $($args),+);
31 writeln!($writer, $fmt, $($args),+)
32 }
33 };
34}
35
36pub fn pad<T: Clone + Copy>(contents: &Vec<&[T]>, padding: usize, default: T) -> Vec<Vec<T>> {
37 let mut r = Vec::with_capacity(contents.len());
38 let mut prefix = vec![vec![default; contents[0].len() + padding * 2]; padding];
39 r.append(&mut prefix);
40
41 for line in contents {
42 let prefix = vec![default; padding];
43 let middle = line.to_vec();
44 let suffix = vec![default; padding];
45
46 r.push(vec![prefix, middle, suffix].into_iter().flatten().collect());
47 }
48
49 let mut suffix = vec![vec![default; contents[0].len() + padding * 2]; padding];
50 r.append(&mut suffix);
51
52 r
53}
54
55pub fn pad_vec<T: Clone + Copy>(contents: &Vec<Vec<T>>, padding: usize, default: T) -> Vec<Vec<T>> {
57 let mut r = Vec::with_capacity(contents.len());
58 let mut prefix = vec![vec![default; contents[0].len() + padding * 2]; padding];
59 r.append(&mut prefix);
60
61 for line in contents {
62 let prefix = vec![default; padding];
63 let middle = line.to_vec();
64 let suffix = vec![default; padding];
65
66 r.push(vec![prefix, middle, suffix].into_iter().flatten().collect());
67 }
68
69 let mut suffix = vec![vec![default; contents[0].len() + padding * 2]; padding];
70 r.append(&mut suffix);
71
72 r
73}
74
75pub fn prep_io(contents: &mut String, day: u8) -> anyhow::Result<(BufWriter<File>, Vec<&str>)> {
76 *contents = read_to_string(format!("inputs/{:02}.txt", day))?;
77 let contents: Vec<&str> = contents.trim().lines().collect();
78
79 let write_file = File::create(format!("outputs/{:02}.txt", day))?;
80 let writer = BufWriter::new(write_file);
81
82 Ok((writer, contents))
83}
84
85pub fn split_and_parse<T: FromStr>(s: &str, delim: &str) -> anyhow::Result<Vec<T>>
86where
87 <T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
88{
89 let mut v = Vec::new();
90 for n in s.split(delim) {
91 v.push(n.parse()?);
92 }
93
94 Ok(v)
95}
96
97pub fn usize_plus_i<T>(u: usize, i: T) -> usize
117where
118 T: TryFrom<usize, Error: fmt::Debug> + ops::Add<Output = T>,
119 usize: TryFrom<T, Error: fmt::Debug>,
120{
121 usize::try_from(T::try_from(u).unwrap() + i).unwrap()
122}
123
124pub fn u8_to_string(c: u8) -> String {
125 String::from_utf8(vec![c]).unwrap()
126}
127
128pub fn split_by_char(s: &str) -> Vec<&str> {
130 s.split("").filter(|c| !c.is_empty()).collect()
131}
132
133pub fn position_2d<T, P>(v: &[Vec<T>], mut predicate: P) -> Option<(usize, usize)>
151where
152 P: FnMut(&T) -> bool,
153{
154 for (y, row) in v.iter().enumerate() {
155 if let Some(x) = row.iter().position(&mut predicate) {
156 return Some((x, y));
157 }
158 }
159
160 None
161}
162
163pub fn gcd<T>(a: T, b: T) -> T
174where
175 T: Copy + ops::Rem<Output = T> + PartialEq + Zero,
176{
177 if b == T::zero() {
178 return a;
179 }
180
181 gcd(b, a % b)
182}
183
184pub fn inc_selector(v: &mut [bool]) -> bool {
200 if v.iter().map(|&b| if b { 1 } else { 0 }).sum::<usize>() == v.len() {
201 return true;
202 }
203
204 let mut last = v.len() - 1;
205 loop {
206 v[last] = !v[last];
207
208 if v[last] {
209 break;
210 }
211
212 match last.checked_sub(1) {
213 None => break,
214 Some(l) => last = l,
215 }
216 }
217
218 false
219}
220
221pub fn fold_while<I, B, F>(it: I, init: B, mut f: F) -> B
238where
239 I: Iterator,
240 F: FnMut(B, I::Item) -> (B, bool),
241{
242 let mut b = init;
243 for v in it {
244 let (new_b, should_continue) = f(b, v);
245 b = new_b;
246 if !should_continue {
247 break;
248 }
249 }
250 b
251}
252
253pub fn abs<T>(i: T) -> T
265where
266 T: PartialOrd + ops::Sub<Output = T> + Zero,
267{
268 if i < T::zero() { T::zero() - i } else { i }
269}