11use std:: cmp:: min;
22
3+ /// Represents possible errors that can occur when calculating the minimum cost path in a matrix.
4+ #[ derive( Debug , PartialEq , Eq ) ]
5+ pub enum MatrixError {
6+ /// Error indicating that the matrix is empty or has empty rows.
7+ EmptyMatrix ,
8+ /// Error indicating that the matrix is not rectangular in shape.
9+ NonRectangularMatrix ,
10+ }
11+
312/// Computes the minimum cost path from the top-left to the bottom-right
413/// corner of a matrix, where movement is restricted to right and down directions.
514///
6- /// The function calculates the minimum path cost by updating a `cost` vector that
7- /// stores cumulative path costs for the current row as it iterates through each
8- /// row of the input `matrix`.
9- ///
1015/// # Arguments
1116///
1217/// * `matrix` - A 2D vector of positive integers, where each element represents
1318/// the cost to step on that cell.
1419///
1520/// # Returns
1621///
17- /// * A single `usize` value representing the minimum path cost to reach the
18- /// bottom-right corner from the top-left corner of the matrix.
22+ /// * `Ok(usize)` - The minimum path cost to reach the bottom-right corner from
23+ /// the top-left corner of the matrix.
24+ /// * `Err(MatrixError)` - An error if the matrix is empty or improperly formatted.
1925///
2026/// # Complexity
2127///
2228/// * Time complexity: `O(m * n)`, where `m` is the number of rows
2329/// and `n` is the number of columns in the input matrix.
2430/// * Space complexity: `O(n)`, as only a single row of cumulative costs
2531/// is stored at any time.
26- pub fn minimum_cost_path ( matrix : Vec < Vec < usize > > ) -> usize {
27- // Initialize the first row of the cost vector using a scan over the first row of matrix
32+ pub fn minimum_cost_path ( matrix : Vec < Vec < usize > > ) -> Result < usize , MatrixError > {
33+ // Check if the matrix is rectangular
34+ if !matrix. iter ( ) . all ( |row| row. len ( ) == matrix[ 0 ] . len ( ) ) {
35+ return Err ( MatrixError :: NonRectangularMatrix ) ;
36+ }
37+
38+ // Check if the matrix is empty or contains empty rows
39+ if matrix. is_empty ( ) || matrix. iter ( ) . all ( |row| row. is_empty ( ) ) {
40+ return Err ( MatrixError :: EmptyMatrix ) ;
41+ }
42+
43+ // Initialize the first row of the cost vector
2844 let mut cost = matrix[ 0 ]
2945 . iter ( )
3046 . scan ( 0 , |acc, & val| {
@@ -45,7 +61,7 @@ pub fn minimum_cost_path(matrix: Vec<Vec<usize>>) -> usize {
4561 }
4662
4763 // The last element in cost contains the minimum path cost to the bottom-right corner
48- cost[ matrix[ 0 ] . len ( ) - 1 ]
64+ Ok ( cost[ matrix[ 0 ] . len ( ) - 1 ] )
4965}
5066
5167#[ cfg( test) ]
@@ -71,28 +87,29 @@ mod tests {
7187 vec![ 2 , 1 , 3 ] ,
7288 vec![ 3 , 2 , 1 ]
7389 ] ,
74- 7
90+ Ok ( 7 )
7591 ) ,
7692 single_element: (
7793 vec![
7894 vec![ 5 ]
7995 ] ,
80- 5
96+ Ok ( 5 )
8197 ) ,
8298 single_row: (
8399 vec![
84100 vec![ 1 , 3 , 2 , 1 , 5 ]
85101 ] ,
86- 12
102+ Ok ( 12 )
87103 ) ,
88104 single_column: (
89105 vec![
90106 vec![ 1 ] ,
91107 vec![ 3 ] ,
92108 vec![ 2 ] ,
93109 vec![ 1 ] ,
94- vec![ 5 ] ] ,
95- 12
110+ vec![ 5 ]
111+ ] ,
112+ Ok ( 12 )
96113 ) ,
97114 large_matrix: (
98115 vec![
@@ -101,31 +118,31 @@ mod tests {
101118 vec![ 3 , 2 , 1 , 3 ] ,
102119 vec![ 4 , 3 , 2 , 1 ]
103120 ] ,
104- 10
121+ Ok ( 10 )
105122 ) ,
106123 uniform_matrix: (
107124 vec![
108125 vec![ 1 , 1 , 1 ] ,
109126 vec![ 1 , 1 , 1 ] ,
110127 vec![ 1 , 1 , 1 ]
111128 ] ,
112- 5
129+ Ok ( 5 )
113130 ) ,
114131 increasing_values: (
115132 vec![
116133 vec![ 1 , 2 , 3 ] ,
117134 vec![ 4 , 5 , 6 ] ,
118135 vec![ 7 , 8 , 9 ]
119136 ] ,
120- 21
137+ Ok ( 21 )
121138 ) ,
122139 high_cost_path: (
123140 vec![
124141 vec![ 1 , 100 , 1 ] ,
125142 vec![ 1 , 100 , 1 ] ,
126143 vec![ 1 , 1 , 1 ]
127144 ] ,
128- 5
145+ Ok ( 5 )
129146 ) ,
130147 complex_matrix: (
131148 vec![
@@ -134,7 +151,27 @@ mod tests {
134151 vec![ 2 , 1 , 8 , 2 ] ,
135152 vec![ 3 , 6 , 9 , 4 ]
136153 ] ,
137- 23
154+ Ok ( 23 )
155+ ) ,
156+ empty_matrix: (
157+ vec![ ] ,
158+ Err ( MatrixError :: EmptyMatrix )
159+ ) ,
160+ empty_row: (
161+ vec![
162+ vec![ ] ,
163+ vec![ ] ,
164+ vec![ ]
165+ ] ,
166+ Err ( MatrixError :: EmptyMatrix )
167+ ) ,
168+ non_rectangular: (
169+ vec![
170+ vec![ 1 , 2 , 3 ] ,
171+ vec![ 4 , 5 ] ,
172+ vec![ 6 , 7 , 8 ]
173+ ] ,
174+ Err ( MatrixError :: NonRectangularMatrix )
138175 ) ,
139176 }
140177}
0 commit comments