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 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}