perf: flatten Grid inner repr to Vec<u8>

This commit is contained in:
Matej Janezic 2024-12-16 21:57:13 +01:00
parent 0000020047
commit 000002103d
Signed by: janezicmatej
GPG Key ID: 4298E230ED37B2C0
1 changed files with 35 additions and 15 deletions

View File

@ -8,24 +8,44 @@ use super::Point;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Grid { pub struct Grid {
grid: Vec<Vec<u8>>, grid: Vec<u8>,
width: usize,
} }
impl FromStr for Grid { impl FromStr for Grid {
type Err = (); type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
let grid = s.lines().map(|x| x.as_bytes().to_vec()).collect(); let mut grid = Vec::with_capacity(s.len());
Ok(Self { grid }) let mut width = None;
for line in s.lines() {
let w = line.len();
if width.is_none() {
width = Some(w);
}
if width.filter(|&x| x == w).is_none() {
panic!("all lines have to be of same length");
}
grid.extend(line.bytes());
}
Ok(Self {
grid,
width: width.unwrap(),
})
} }
} }
impl Display for Grid { impl Display for Grid {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for row in self.grid.iter() { for (idx, cell) in self.grid.iter().enumerate() {
for cell in row.iter() { write!(f, "{}", *cell as char)?;
write!(f, "{}", *cell as char)?; if idx > 0 && idx % self.width == 0 {
writeln!(f)?;
} }
writeln!(f)?;
} }
Ok(()) Ok(())
} }
@ -34,33 +54,33 @@ impl Display for Grid {
impl Index<Point> for Grid { impl Index<Point> for Grid {
type Output = u8; type Output = u8;
fn index(&self, index: Point) -> &Self::Output { fn index(&self, index: Point) -> &Self::Output {
&self.grid[index.i][index.j] &self.grid[index.i * self.width + index.j]
} }
} }
impl IndexMut<Point> for Grid { impl IndexMut<Point> for Grid {
fn index_mut(&mut self, index: Point) -> &mut Self::Output { fn index_mut(&mut self, index: Point) -> &mut Self::Output {
&mut self.grid[index.i][index.j] &mut self.grid[index.i * self.width + index.j]
} }
} }
impl Grid { impl Grid {
pub fn find(&self, f: u8) -> Option<Point> { pub fn find(&self, f: u8) -> Option<Point> {
let (i, j, _) = self let n = self
.grid .grid
.iter() .iter()
.enumerate() .enumerate()
.flat_map(|(i, x)| x.iter().copied().enumerate().map(move |(j, y)| (i, j, y))) .find(|&(_, &x)| x == f)
.find(|x| x.2 == f)?; .map(|x| x.0)?;
Some(Point::new(i, j)) Some(Point::new(n / self.width, n % self.width))
} }
pub fn get(&self, p: &Point) -> Option<&u8> { pub fn get(&self, p: &Point) -> Option<&u8> {
self.grid.get(p.i).and_then(|r| r.get(p.j)) self.grid.get(p.i * self.width + p.j)
} }
pub fn get_mut(&mut self, p: &Point) -> Option<&mut u8> { pub fn get_mut(&mut self, p: &Point) -> Option<&mut u8> {
self.grid.get_mut(p.i).and_then(|r| r.get_mut(p.j)) self.grid.get_mut(p.i * self.width + p.j)
} }
} }