diff --git a/src/lcs.rs b/src/lcs.rs new file mode 100644 index 0000000..c1c714b --- /dev/null +++ b/src/lcs.rs @@ -0,0 +1,74 @@ +use std::cmp::max; +use std::str::Chars; +use crate::matrix::Matrix; + +pub fn diff(a: &str, b: &str) { + let m = build_matrix(a, b); + print_diff(m, &mut a.chars(), &mut b.chars(), a.len() - 1, b.len() - 1); +} + +fn build_matrix(a: &str, b: &str) -> Matrix { + let mut a = a.chars(); + let mut b = b.chars(); + let mut m = Matrix::new(*(&a.count()), *(&b.count()), 0i32); + + for i in 0..a.count() { + for j in 0..b.count() { + let x = a.nth(i).unwrap(); + let y = b.nth(j).unwrap(); + + let v = if x == y { + if i == 0 || j == 0 { + 0 + } else { + m.get(i - 1, j - 1).unwrap() + 1 + } + } else { + max( + if j == 0 { 0 } else { *m.get(i, j - 1).unwrap() }, + if i == 0 { 0 } else { *m.get(i - 1, j).unwrap() }) + }; + + m.set(v, i, j).unwrap(); + } + } + + m +} + +fn print_diff(m: Matrix, a: &mut Chars, b: &mut Chars, i: usize, j: usize) { + if i < 0 && j < 0 { + println!(); + return; + } + + let char_i = a.nth(i).unwrap(); + let char_j = b.nth(j).unwrap(); + + if i < 0 { + print_diff(m, a, b, i, j - 1); + println!("+ {char_i}"); + return; + } + + if j < 0 { + print_diff(m, a, b, i - 1, j); + println!("- {char_j}"); + return; + } + + if char_i == char_j { + print_diff(m, a, b, i - 1, j - 1); + println!(" {char_i}"); + return; + } + + if m.get(i, j - 1).unwrap() >= m.get(i - 1, j).unwrap() { + print_diff(m, a, b, i, j - 1); + println!("+ {char_j}"); + return; + } + + print_diff(m, a, b, i - 1, j); + println!("- {char_i}"); +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index f539d35..864f08f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,50 +1,12 @@ -use std::cmp::min; -use std::io; -use crate::matrix::Matrix; +use crate::lcs::diff; mod matrix; +mod lcs; -const ADD_VAL: i32 = 1; -const MATCH_VAL: i32 = 0; +fn main() { + let a = "let a = \"ABCDE\";"; + let b = "let b = \"ABCDE\";"; -fn main() -> io::Result<()> { - let str_a = "String A"; - let str_b = "String B"; - - let mut diff_mat = Matrix::new(str_a.len(), str_b.len(), 0i32); - - for col in 1..diff_mat.col_count { - let previous = diff_mat.get(0, col - 1).unwrap(); - diff_mat.set(previous + ADD_VAL, 0, col).expect("Failed to initialize diff matrix"); - } - - for row in 1..diff_mat.row_count { - let previous = diff_mat.get(row - 1, 0).unwrap(); - diff_mat.set(previous - ADD_VAL, row, 0).expect("Failed to initialize diff matrix"); - } - - for row in 1..diff_mat.row_count { - for col in 1..diff_mat.col_count { - let char_a = str_a.chars().nth(row).unwrap(); - let char_b = str_b.chars().nth(col).unwrap(); - - let add_from = diff_mat.get(row, col - 1).unwrap(); - let sub_from = diff_mat.get(row - 1, col).unwrap(); - let substitute_from = diff_mat.get(row - 1, col - 1).unwrap(); - - let add = add_from + ADD_VAL; - let sub = sub_from - ADD_VAL; - let substitute = substitute_from + if char_a == char_b { - MATCH_VAL - } else { - 1 - }; - - let val = min(add, min(sub, substitute)); - diff_mat.set(val, row, col).unwrap(); - } - } - - diff_mat.print(); - Ok(()) + diff(a, b); } +