Skip to content

Instantly share code, notes, and snippets.

@ratijas
Forked from rust-play/playground.rs
Created April 8, 2020 13:37
Show Gist options
  • Save ratijas/c0122a7ec276966513f8f6e92bd080d0 to your computer and use it in GitHub Desktop.
Save ratijas/c0122a7ec276966513f8f6e92bd080d0 to your computer and use it in GitHub Desktop.

Revisions

  1. ratijas revised this gist Apr 8, 2020. No changes.
  2. @rust-play rust-play created this gist Apr 8, 2020.
    187 changes: 187 additions & 0 deletions playground.rs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,187 @@
    use std::{fmt, ops};

    pub struct Array2D<T> {
    width: usize,
    height: usize,
    data: Box<[T]>,
    }

    impl<T> Array2D<T> {
    pub fn new(size: (usize, usize)) -> Self
    where T: Default
    {
    let (width, height) = size;
    assert_ne!(width, 0);
    assert_ne!(height, 0);
    let size = width.checked_mul(height).expect("Array of this size would not fit into memory");
    let mut vec = Vec::with_capacity(size);
    vec.extend(std::iter::repeat_with(T::default).take(size));
    let data = vec.into_boxed_slice();
    Array2D {
    width,
    height,
    data,
    }
    }

    pub fn width(&self) -> usize { self.width }

    pub fn height(&self) -> usize { self.height }

    pub fn len(&self) -> usize {
    // probably faster than multiplication
    self.data.len()
    }

    fn make_index(&self, xy: (usize, usize)) -> usize {
    let (x, y) = xy;
    assert!(x < self.width);
    assert!(y < self.height);
    y * self.width + x
    }

    pub fn column(&self, column_index: usize) -> Column<T> {
    assert!(column_index < self.width());
    Column::new(self, column_index)
    }

    pub fn columns<'a>(&'a self) -> impl Iterator<Item=Column<'a, T>> + 'a {
    (0..self.width()).map(move |x| self.column(x))
    }

    pub fn row(&self, row_index: usize) -> Row<T> {
    assert!(row_index < self.height());
    Row::new(self, row_index)
    }

    pub fn rows<'a>(&'a self) -> impl Iterator<Item=Row<'a, T>> + 'a {
    (0..self.height()).map(move |y| self.row(y))
    }
    }

    impl<T> ops::Index<(usize, usize)> for Array2D<T> {
    type Output = T;

    fn index(&self, xy: (usize, usize)) -> &T {
    let index = self.make_index(xy);
    &self.data[index]
    }
    }

    impl<T> ops::IndexMut<(usize, usize)> for Array2D<T> {
    fn index_mut(&mut self, xy: (usize, usize)) -> &mut T {
    let index = self.make_index(xy);
    &mut self.data[index]
    }
    }

    impl<T> fmt::Display for Array2D<T>
    where T: fmt::Display
    {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    "Array2D([\n".fmt(f)?;
    for row in self.rows() {
    " [".fmt(f)?;
    for (x, item) in row.enumerate() {
    write!(f, "{}", item)?;
    if x != (self.width() - 1) {
    ", ".fmt(f)?;
    }
    }
    "]\n".fmt(f)?;
    }
    "])".fmt(f)?;
    Ok(())
    }
    }

    pub struct Row<'a, T> {
    array: &'a Array2D<T>,
    row: usize,
    current_column: usize,
    }

    impl<'a, T> Row<'a, T> {
    pub fn new(array: &'a Array2D<T>, row: usize) -> Self {
    assert!(row < array.height);

    Row {
    array,
    row,
    current_column: 0
    }
    }

    pub fn current_column(&self) -> usize {
    self.current_column
    }
    }

    impl<'a, T> Iterator for Row<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
    if self.current_column >= self.array.width() {
    None
    } else {
    let index = (self.current_column, self.row);
    let item = &self.array[index];
    self.current_column += 1;
    Some(item)
    }
    }
    }

    pub struct Column<'a, T> {
    array: &'a Array2D<T>,
    column: usize,
    current_row: usize,
    }

    impl<'a, T> Column<'a, T> {
    pub fn new(array: &'a Array2D<T>, column: usize) -> Self {
    assert!(column < array.width);

    Column {
    array,
    column,
    current_row: 0
    }
    }

    pub fn current_row(&self) -> usize {
    self.current_row
    }
    }

    impl<'a, T> Iterator for Column<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
    if self.current_row >= self.array.height() {
    None
    } else {
    let index = (self.column, self.current_row);
    let item = &self.array[index];
    self.current_row += 1;
    Some(item)
    }
    }
    }

    fn incremental_array(size: (usize, usize)) -> Array2D<u8> {
    let mut array = Array2D::new(size);
    let mut item = 0u8;
    for x in 0..array.width() {
    for y in 0..array.height() {
    array[(x, y)] = item;
    item += 1;
    }
    }
    array
    }

    fn main() {
    let a = incremental_array((10, 15));
    println!("{}", a);
    }