use std::io::Read; use std::collections::VecDeque; use std::collections::HashMap; use std::fmt::{Display, Formatter}; use std::fs::File; use std::hash::Hash; use std::ops::{Index, IndexMut}; use std::str::FromStr; use color_eyre::{eyre}; use eyre::eyre; pub fn load(filename: &str) -> eyre::Result { let mut file = File::open(filename)?; let mut data = String::new(); file.read_to_string(&mut data)?; Ok(data) } pub struct LineParser<'a, T: FromStr> { it: std::str::Lines<'a>, convert: fn(&str) -> Result::Err> } impl<'a, T: FromStr> Iterator for LineParser<'a, T> { type Item = Result::Err>; fn next(&mut self) -> Option { self.it.next().map(|s| (self.convert)(s) ) } } // define a trait so that we can attach it to String pub trait ParseLines { fn parse_lines(&self) -> LineParser<'_, T>; } impl ParseLines for str { fn parse_lines(&self) -> LineParser<'_, T> { LineParser { it: self.lines(), convert: str::parse:: } } } impl ParseLines for String { fn parse_lines(&self) -> LineParser<'_, T> { self[..].parse_lines::() } } pub trait IterExt: Iterator { fn take_pair(&mut self) -> eyre::Result<(Self::Item, Self::Item)> { let a = match self.next() { Some(v) => v, None => return Err(eyre!("Not enough values to unpack")), }; let b = match self.next() { Some(v) => v, None => return Err(eyre!("Not enough values to unpack")), }; Ok((a, b)) } fn max_n(&mut self, n: usize) -> eyre::Result> where Self: Sized, Self::Item: Ord, { let mut items = VecDeque::with_capacity(n); while let Some(item) = self.next() { for i in 0..=items.len() { if i < items.len() && item > items[i] { if items.len() == n { items.pop_back(); } items.insert(i, item); break; } else if i == items.len() && i < n { items.push_back(item); break; } } } if items.len() < n { Err(eyre!("Not enough values to take the maximum {}", n)) } else { Ok(items) } } } impl IterExt for I {} // 2d container, functions kind of like a "vec of vecs" but all data is stored in a single vec for memory contiguity pub struct Vec2 { data: Vec, columns: usize, } pub struct NeighborCoords { num_rows: usize, num_cols: usize, start_row: usize, start_col: usize, i: usize, } impl Iterator for NeighborCoords { type Item = (usize, usize); fn next(&mut self) -> Option { if self.i > 8 { return None; } let (rel_row, rel_col) = (self.i / 3, self.i % 3); self.i += 1; if rel_row == 1 && rel_col == 1 { return self.next(); } let row_offset = self.start_row + rel_row; let col_offset = self.start_col + rel_col; // the "neighbor window" is off by 1, so we make the comparisons off by 1 as well if row_offset > 0 && row_offset <= self.num_rows && col_offset > 0 && col_offset <= self.num_cols { Some((row_offset - 1, col_offset - 1)) } else { self.next() } } } pub struct RectNeighbors { nc: NeighborCoords, } impl Iterator for RectNeighbors { type Item = (usize, usize); fn next(&mut self) -> Option { if let Some((row, col)) = self.nc.next() { if row == self.nc.start_row || col == self.nc.start_col { return Some((row, col)); } else { return self.next(); } } return None } } #[allow(dead_code)] impl Vec2 { pub fn new(columns: usize) -> Vec2 { Vec2 {data: Vec::::new(), columns} } pub fn with_capacity(rows: usize, columns: usize) -> Vec2 { Vec2 {data: Vec::::with_capacity(rows * columns), columns} } pub fn push>(&mut self, row: S) { self.data.extend(row.into_iter()); } pub fn row_count(&self) -> usize { self.data.len() / self.columns } pub fn col_count(&self) -> usize { self.columns } pub fn coords(&self, i: usize) -> (usize, usize) { // convert underlying index into 2d coordinates (i / self.columns, i % self.columns) } pub fn offset(&self, row: usize, col: usize) -> usize { // and the reverse self.columns * row + col } pub fn rows(&self) -> impl Iterator { self.data.chunks_exact(self.columns) } pub fn rows_mut(&mut self) -> impl Iterator { self.data.chunks_exact_mut(self.columns) } pub fn values(&self) -> impl Iterator { self.data.iter() } pub fn values_mut(&mut self) -> impl Iterator { self.data.iter_mut() } pub fn neighbor_coords(&self, row: usize, col: usize) -> NeighborCoords { NeighborCoords { num_rows: self.row_count(), num_cols: self.col_count(), start_row: row, start_col: col, i: 0, } } pub fn rect_neighbors(&self, row: usize, col: usize) -> RectNeighbors { RectNeighbors {nc: self.neighbor_coords(row, col)} } pub fn get(&self, row: usize, col: usize) -> &T { &self.data[self.offset(row, col)] } pub fn get_mut(&mut self, row: usize, col: usize) -> &mut T { self.data.index_mut(self.offset(row, col)) } pub fn set(&mut self, row: usize, col: usize, val: T) { let existing = self.data.index_mut(self.offset(row, col)); *existing = val; } } #[allow(dead_code)] impl Vec2 { pub fn fill(&mut self, value: T) { for i in 0..self.data.len() { self.data[i] = value; } } pub fn fill_to_cap(&mut self, value: T) { self.fill(value); for _i in self.data.len()..self.data.capacity() { self.data.push(value); } } } impl Index for Vec2 { type Output = [T]; fn index(&self, index: usize) -> &Self::Output { let start = self.columns * index; &self.data[start..(start + self.columns)] } } impl IndexMut for Vec2 { fn index_mut(&mut self, index: usize) -> &mut Self::Output { let start = self.columns * index; &mut self.data[start..(start + self.columns)] } } impl Display for Vec2 { fn fmt(&self, f: &mut Formatter) -> std::fmt::Result { for row in self.rows() { write!(f, "[")?; for (i, v) in row.iter().enumerate() { if i > 0 {write!(f, "")?;} write!(f, "{}", v)?; } write!(f, "]\n")?; } Ok(()) } } #[derive(Debug, Clone)] pub struct Counter { data: HashMap } #[allow(dead_code)] impl Counter where K: Eq + Hash, { pub fn new() -> Self { Counter {data: HashMap::::new()} } pub fn inc(&mut self, key: K) { let v = self.data.entry(key).or_insert(0); *v += 1; } pub fn inc_by(&mut self, key: K, increment: usize) { let v = self.data.entry(key).or_insert(0); *v += increment; } pub fn dec(&mut self, key: K) { let v = self.data.entry(key).or_insert(0); if *v > 0 { *v -= 1; } } pub fn dec_by(&mut self, key: K, decrement: usize) { let v = self.data.entry(key).or_insert(0); if *v >= decrement { *v -= decrement; } } pub fn get(&mut self, key: &K) -> usize { *self.data.get(key).unwrap_or(&0) } pub fn set(&mut self, key: K, value: usize) { self.data.insert(key, value); } pub fn iter(&self) -> impl Iterator { self.data.iter().map(|(k, v)| (k, *v)) } }