|
| 1 | + |
| 2 | + |
| 3 | +///find row and column of given key in given matrix |
| 4 | +/// m is row count and n is column count |
| 5 | +#[derive(PartialEq, Eq, Debug)] |
| 6 | +pub struct SortedMatrixResult { |
| 7 | + pub column: i64, |
| 8 | + pub row: i64, |
| 9 | +} |
| 10 | +#[derive(PartialEq, Eq, Debug)] |
| 11 | +pub enum SortedMatrixErr { |
| 12 | + KeyNotFound, |
| 13 | + InvalidArgument(String), |
| 14 | +} |
| 15 | +pub fn search_in_a_sorted_matrix( |
| 16 | + mat: Vec<Vec<f64>>, |
| 17 | + m: usize, |
| 18 | + n: usize, |
| 19 | + key: f64, |
| 20 | +) -> Result<SortedMatrixResult, SortedMatrixErr> { |
| 21 | + if m < 1 { |
| 22 | + return Err(SortedMatrixErr::InvalidArgument(String::from( |
| 23 | + "m must be greater than or equal to 1", |
| 24 | + ))); |
| 25 | + } |
| 26 | + |
| 27 | + if n < 1 { |
| 28 | + return Err(SortedMatrixErr::InvalidArgument(String::from( |
| 29 | + "n must be greater than or equal to 1", |
| 30 | + ))); |
| 31 | + } |
| 32 | + |
| 33 | + if mat.is_empty() { |
| 34 | + return Err(SortedMatrixErr::InvalidArgument(String::from( |
| 35 | + "mat must be non-empty", |
| 36 | + ))); |
| 37 | + } |
| 38 | + |
| 39 | + let (mut i, mut j) = (m - 1, 0); |
| 40 | + |
| 41 | + while j < n { |
| 42 | + if (mat[i][j] - key).abs() < f64::EPSILON { |
| 43 | + return Ok(SortedMatrixResult { |
| 44 | + column: (j + 1) as i64, |
| 45 | + row: (i + 1) as i64, |
| 46 | + }); |
| 47 | + } |
| 48 | + if key < mat[i][j] { |
| 49 | + i -= 1; |
| 50 | + } else { |
| 51 | + j += 1; |
| 52 | + } |
| 53 | + } |
| 54 | + Err(SortedMatrixErr::KeyNotFound) |
| 55 | +} |
| 56 | +#[cfg(test)] |
| 57 | +mod tests { |
| 58 | + use super::*; |
| 59 | + macro_rules! test_search_in_a_sorted_matrix_err { |
| 60 | + ($($name:ident: $inputs:expr,)*) => { |
| 61 | + $( |
| 62 | + #[test] |
| 63 | + fn $name() { |
| 64 | + let ((mat,m,n,key), expected) = $inputs; |
| 65 | + assert_eq!(search_in_a_sorted_matrix(mat,m,n,key).unwrap_err(), expected); |
| 66 | + } |
| 67 | + )* |
| 68 | + } |
| 69 | + } |
| 70 | + macro_rules! test_search_in_a_sorted_matrix { |
| 71 | + ($($name:ident: $inputs:expr,)*) => { |
| 72 | + $( |
| 73 | + #[test] |
| 74 | + fn $name() { |
| 75 | + let ((mat,m,n,key), expected) = $inputs; |
| 76 | + assert_eq!(search_in_a_sorted_matrix(mat,m,n,key).unwrap(), expected); |
| 77 | + } |
| 78 | + )* |
| 79 | + } |
| 80 | + } |
| 81 | + |
| 82 | + test_search_in_a_sorted_matrix_err! { |
| 83 | + key_not_found_test: ((vec![vec![1.0,1.0],vec![1.0,1.0]],2,2,4.0), SortedMatrixErr::KeyNotFound), |
| 84 | + invalid_m_test: ((vec![vec![1.0,1.0],vec![1.0,1.0]],0,2,4.0), SortedMatrixErr::InvalidArgument(String::from("m must be greater than or equal to 1"))), |
| 85 | + invalid_n_test: ((vec![vec![1.0,1.0],vec![1.0,1.0]],2,0,4.0), SortedMatrixErr::InvalidArgument(String::from("n must be greater than or equal to 1"))), |
| 86 | + } |
| 87 | + |
| 88 | + test_search_in_a_sorted_matrix! { |
| 89 | + kgeneral_test1: ((vec![vec![2.1, 5.0, 7.0], vec![4.0, 8.0, 13.0], vec![9.0, 11.0, 15.0], vec![12.0, 17.0, 20.0]], 3, 3, 2.1), SortedMatrixResult{ |
| 90 | + row:1, |
| 91 | + column:1 |
| 92 | + }), |
| 93 | + kgeneral_test2: (( vec![vec![2.0, 5.0, 7.0], vec![4.0, 8.0, 13.0], vec![9.0, 11.0, 15.0], vec![12.0, 17.0, 20.0]], 3, 3, 5.0), SortedMatrixResult{ |
| 94 | + row:1, |
| 95 | + column:2 |
| 96 | + }), |
| 97 | + } |
| 98 | +} |
0 commit comments