advtools/
lib.rs

1use std::cell::RefCell;
2use std::path::Path;
3use std::fmt::Display;
4use std::sync::atomic::{AtomicI32, Ordering};
5
6pub use rayon;
7pub use itertools;
8
9pub mod input;
10pub mod grid;
11
12pub mod prelude {
13    pub use std::collections::VecDeque;
14    pub use std::collections::hash_map::Entry;
15    pub use std::iter::once;
16
17    pub use hashbrown::{HashMap, HashSet};
18    pub use itertools::{Itertools, iproduct};
19    pub use regex::{Regex, Captures};
20    pub use odds::slice::rotate_left;
21    pub use arrayvec::ArrayVec;
22
23    pub fn rotate_right<T>(t: &mut [T], n: usize) {
24        let m = t.len() - n;
25        odds::slice::rotate_left(t, m);
26    }
27
28    pub struct Uids<T> {
29        map: hashbrown::HashMap<T, usize>
30    }
31
32    impl<T: std::hash::Hash + Eq> Uids<T> {
33        pub fn new() -> Uids<T> {
34            Uids { map: Default::default() }
35        }
36
37        pub fn get_id(&mut self, k: T) -> usize {
38            let n = self.map.len();
39            *self.map.entry(k).or_insert(n)
40        }
41    }
42
43    impl<T, Q> std::ops::Index<&Q> for Uids<T>
44    where T: std::hash::Hash + Eq + std::borrow::Borrow<Q>, Q: std::hash::Hash + Eq + ?Sized
45    {
46        type Output = usize;
47        fn index(&self, q: &Q) -> &usize {
48            &self.map[&q]
49        }
50    }
51
52    /// Perform a binary search
53    pub fn binary_search<I, F>(mut low: I, mut high: I, mut test: F) -> I
54    where I: num::Integer + Copy + From<u8>, F: FnMut(I) -> bool
55    {
56        loop {
57            if low + I::one() == high {
58                return high;
59            }
60            let guess = (low + high) / I::from(2);
61            if test(guess) {
62                high = guess;
63            } else {
64                low = guess;
65            }
66        }
67    }
68}
69
70thread_local! {
71    static INPUT: RefCell<Option<&'static str>> = Default::default();
72}
73
74static OUT_CONTROL: AtomicI32 = AtomicI32::new(1);
75
76pub fn bench_mode(path: impl AsRef<Path>) {
77    OUT_CONTROL.store(0, Ordering::SeqCst);
78    INPUT.with(|k| *k.borrow_mut() = Some(
79        Box::leak(
80            std::fs::read_to_string(path.as_ref()).unwrap_or_else(
81                |e| panic!("could not read input file: {}", e)).into()
82        )
83    ));
84}
85
86pub fn print(part: &str, value: impl Display) {
87    if OUT_CONTROL.load(Ordering::SeqCst) > 0 {
88        let n = OUT_CONTROL.fetch_add(1, Ordering::SeqCst);
89        println!("{}. {}: {}", n, part, value);
90    }
91}
92
93pub fn verify(part: &str, value: impl Display, check: impl Display) {
94    let value_str = format!("{}", value);
95    let check_str = format!("{}", check);
96    assert_eq!(value_str, check_str);
97    if OUT_CONTROL.load(Ordering::SeqCst) > 0 {
98        let n = OUT_CONTROL.fetch_add(1, Ordering::SeqCst);
99        println!("{}. {}: {}", n, part, value_str);
100    }
101}