CS110L-Lab/week2/rdiff/src/grid.rs
ridethepig 65fe3e800b rdiif
2023-02-23 07:31:06 +00:00

109 lines
3.4 KiB
Rust

// Grid implemented as flat vector
pub struct Grid {
num_rows: usize,
num_cols: usize,
elems: Vec<usize>,
}
impl Grid {
/// Returns a Grid of the specified size, with all elements pre-initialized to zero.
pub fn new(num_rows: usize, num_cols: usize) -> Grid {
Grid {
num_rows: num_rows,
num_cols: num_cols,
// This syntax uses the vec! macro to create a vector of zeros, initialized to a
// specific length
// https://stackoverflow.com/a/29530932
elems: vec![0; num_rows * num_cols],
}
}
pub fn size(&self) -> (usize, usize) {
(self.num_rows, self.num_cols)
}
/// Returns the element at the specified location. If the location is out of bounds, returns
/// None.
///
/// Note to students: this function also could have returned Result. It's a matter of taste in
/// how you define the semantics; many languages raise exceptions for out-of-bounds exceptions,
/// but others argue that makes code needlessly complex. Here, we decided to return Option to
/// give you more practice with Option :) and because this similar library returns Option:
/// https://docs.rs/array2d/0.2.1/array2d/struct.Array2D.html
pub fn get(&self, row: usize, col: usize) -> Option<usize> {
if row >= self.num_rows || col >= self.num_cols {
None
}
else {
Some(self.elems[row * self.num_cols + col])
}
}
/// Sets the element at the specified location to the specified value. If the location is out
/// of bounds, returns Err with an error message.
pub fn set(&mut self, row: usize, col: usize, val: usize) -> Result<(), &'static str> {
if row >= self.num_rows || col >= self.num_cols {
Err("Outof Boundry")
}
else {
self.elems[row * self.num_cols + col] = val;
Ok(())
}
}
/// Prints a visual representation of the grid. You can use this for debugging.
pub fn display(&self) {
for row in 0..self.num_rows {
let mut line = String::new();
for col in 0..self.num_cols {
line.push_str(&format!("{}, ", self.get(row, col).unwrap()));
}
println!("{}", line);
}
}
/// Resets all the elements to zero.
pub fn clear(&mut self) {
for i in self.elems.iter_mut() {
*i = 0;
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_grid() {
let n_rows = 4;
let n_cols = 3;
let mut grid = Grid::new(n_rows, n_cols);
// Initialize grid
for r in 0..n_rows {
for c in 0..n_cols {
assert!(
grid.set(r, c, r * n_cols + c).is_ok(),
"Grid::set returned Err even though the provided bounds are valid!"
);
}
}
// Note: you need to run "cargo test -- --nocapture" in order to see output printed
println!("Grid contents:");
grid.display();
// Make sure the values are what we expect
for r in 0..n_rows {
for c in 0..n_cols {
assert!(
grid.get(r, c).is_some(),
"Grid::get returned None even though the provided bounds are valid!"
);
assert_eq!(grid.get(r, c).unwrap(), r * n_cols + c);
}
}
}
}