edit_dist/
matrix.rs

1use std::fmt;
2use std::ops::{Index, IndexMut};
3
4/// Type being used for selecting cells from a matrix
5pub type Selector = (usize, usize);
6
7/// 2D matrix with given size of T-typed elements
8pub struct Matrix<T> {
9    data: Vec<T>,
10    width: usize,
11    height: usize,
12}
13
14impl<T> Matrix<T>
15where
16    T: Default + Clone,
17{
18    /// Create a new instance of Matrix, with given size
19    ///
20    /// # Arguments
21    /// * `width` - Width of a matrix
22    /// * `height` - Height of a matrix
23    ///
24    /// # Examples
25    /// ```
26    /// let matrix = Matrix::new(3, 7);
27    /// ```
28    pub fn new(width: usize, height: usize) -> Self {
29        Matrix {
30            data: vec![T::default(); width * height],
31            width,
32            height,
33        }
34    }
35
36    /// Get raw 1D index for current matrix and given selector
37    ///
38    /// # Arguments
39    /// * `selector` - Selector to the specific cell
40    ///
41    /// # Examples
42    /// ```
43    /// let idx = self.get_index((2, 3));
44    /// ```
45    fn get_index(&self, selector: Selector) -> Option<usize> {
46        let (y, x) = selector;
47        let index = y * self.width + x;
48
49        if index < self.width * self.height {
50            Some(index)
51        } else {
52            None
53        }
54    }
55
56    /// Get read-only reference to the specific cell
57    ///
58    /// # Arguments
59    /// * `selector` - Selector to the specific cell
60    ///
61    /// # Examples
62    /// ```
63    /// let matrix = Matrix::new(7, 3);
64    /// // ...
65    /// match matrix.get((4, 2)) {
66    ///     Ok(reference) => {
67    ///         // ...
68    ///     },
69    ///     None => {
70    ///         /// ...
71    ///     }
72    /// }
73    /// ```
74    pub fn get(&self, selector: Selector) -> Option<&T> {
75        match self.get_index(selector) {
76            Some(index) => self.data.get(index),
77            None => None,
78        }
79    }
80
81    /// Get a mutable reference to the specific cell
82    ///
83    /// # Arguments
84    /// * `selector` - Selector to the specific cell
85    ///
86    /// # Examples
87    /// ```
88    /// let mut matrix = Matrix::new(7, 3);
89    /// // ...
90    /// match matrix.get_mut((4, 2)) {
91    ///     Ok(reference) => {
92    ///         // ...
93    ///     },
94    ///     None => {
95    ///         /// ...
96    ///     }
97    /// }
98    /// ```
99    pub fn get_mut(&mut self, selector: Selector) -> Option<&mut T> {
100        match self.get_index(selector) {
101            Some(index) => self.data.get_mut(index),
102            None => None,
103        }
104    }
105
106    /// Get width of a matrix
107    pub fn width(&self) -> usize {
108        self.width
109    }
110
111    /// Get height of a matrix
112    pub fn height(&self) -> usize {
113        self.height
114    }
115}
116
117impl<T> Index<Selector> for Matrix<T>
118where
119    T: Default + Clone,
120{
121    type Output = T;
122
123    /// Return read-only reference to the specific cell or panic in case of error
124    ///
125    /// # Arguments
126    /// * `selector` - Selector of the specific cell
127    ///
128    /// # Examples
129    /// ```
130    /// let matrix = Matrix::new(3, 7);
131    /// // ...
132    /// let value = matrix[(0, 0)]
133    /// ```
134    fn index(&self, selector: Selector) -> &Self::Output {
135        self.get(selector)
136            .unwrap_or_else(|| panic!("Invalid index ({}, {})", selector.0, selector.1))
137    }
138}
139
140impl<T> IndexMut<Selector> for Matrix<T>
141where
142    T: Default + Clone,
143{
144    /// Return read-only reference to the specific cell or panic in case of error
145    ///
146    /// # Arguments
147    /// * `selector` - Selector of the specific cell
148    ///
149    /// # Examples
150    /// ```
151    /// let matrix = Matrix::new(3, 7);
152    /// // ...
153    /// let value = matrix[(0, 0)]
154    /// ```
155    fn index_mut(&mut self, selector: Selector) -> &mut Self::Output {
156        self.get_mut(selector)
157            .unwrap_or_else(|| panic!("Invalid index ({}, {})", selector.0, selector.1))
158    }
159}
160
161impl<T> fmt::Display for Matrix<T>
162where
163    T: Default + Clone + fmt::Display,
164{
165    /// Implement displaying a matrix
166    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
167        for y in 0..self.height() {
168            for x in 0..self.width() - 1 {
169                write!(f, "{} ", self[(y, x)])?;
170            }
171            writeln!(f, "{}", self[(y, self.width() - 1)])?;
172        }
173
174        Ok(())
175    }
176}
177
178#[cfg(test)]
179mod test {
180    use super::*;
181
182    #[test]
183    fn test_get_index() {
184        let matrix: Matrix<u32> = Matrix::new(3, 3);
185
186        assert_eq!(matrix.get_index((0, 0)), Some(0));
187        assert_eq!(matrix.get_index((0, 1)), Some(1));
188        assert_eq!(matrix.get_index((0, 2)), Some(2));
189        assert_eq!(matrix.get_index((1, 0)), Some(3));
190        assert_eq!(matrix.get_index((1, 1)), Some(4));
191        assert_eq!(matrix.get_index((1, 2)), Some(5));
192        assert_eq!(matrix.get_index((2, 0)), Some(6));
193        assert_eq!(matrix.get_index((2, 1)), Some(7));
194        assert_eq!(matrix.get_index((2, 2)), Some(8));
195    }
196
197    #[test]
198    fn test_get() {
199        let matrix = Matrix::new(3, 3);
200        // Default value should be 0
201        assert_eq!(matrix.get((1, 1)), Some(0).as_ref());
202    }
203
204    #[test]
205    fn test_get_mut() {
206        let mut matrix = Matrix::new(3, 3);
207        if let Some(reference) = matrix.get_mut((1, 0)) {
208            *reference = 112;
209        }
210
211        assert_eq!(matrix.get((1, 0)), Some(112).as_ref());
212    }
213
214    #[test]
215    fn test_index() {
216        let matrix = Matrix::<u32>::new(3, 3);
217        // Default value should be 0
218        assert_eq!(matrix[(1, 1)], 0u32);
219    }
220
221    #[test]
222    fn test_index_mut() {
223        let mut matrix = Matrix::<u32>::new(3, 3);
224        matrix[(1, 1)] = 112;
225
226        assert_eq!(matrix[(1, 1)], 112u32);
227    }
228}