Skip to content

Commit

Permalink
updated tests
Browse files Browse the repository at this point in the history
  • Loading branch information
yokurang committed Aug 15, 2024
1 parent b5068e3 commit 758019a
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 167 deletions.
108 changes: 4 additions & 104 deletions lib/WordDiff.ml
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,6 @@ let lcs xs' ys' =
done;
a.(0).(0)

let edit_distance (type a) (compare : a -> a -> bool) (s : a array)
(t : a array) : int =
let memo = Hashtbl.create ((Array.length s + 1) * (Array.length t + 1)) in

let rec edit_distance_helper i j =
match (i, j) with
| 0, x | x, 0 -> x
| i, j -> (
match Hashtbl.find_opt memo (i, j) with
| Some result -> result
| None ->
let result =
let cost_to_drop_both =
if compare s.(i - 1) t.(j - 1) then 0 else 1
in
min
(min
(edit_distance_helper (i - 1) j + 1)
(edit_distance_helper i (j - 1) + 1))
(edit_distance_helper (i - 1) (j - 1) + cost_to_drop_both)
in
Hashtbl.add memo (i, j) result;
result)
in
edit_distance_helper (Array.length s) (Array.length t)

let diff_words (s1 : string) (s2 : string) : line_content * line_content =
let words1 = Array.to_list (string_to_words s1) in
let words2 = Array.to_list (string_to_words s2) in
Expand Down Expand Up @@ -77,85 +51,11 @@ let diff_words (s1 : string) (s2 : string) : line_content * line_content =

construct_diff words1 words2 common [] []

let pair_lines lines1 lines2 =
let distances =
Array.make_matrix (Array.length lines1) (Array.length lines2) 0
in
for i = 0 to Array.length lines1 - 1 do
for j = 0 to Array.length lines2 - 1 do
distances.(i).(j) <-
edit_distance ( = )
(string_to_words lines1.(i))
(string_to_words lines2.(j))
done
done;

(* greedily pair lines based on minimum distance *)
let paired = ref [] in
let used1 = Array.make (Array.length lines1) false in
let used2 = Array.make (Array.length lines2) false in

for _ = 1 to min (Array.length lines1) (Array.length lines2) do
let min_dist = ref max_int in
let min_i = ref (-1) in
let min_j = ref (-1) in

for i = 0 to Array.length lines1 - 1 do
for j = 0 to Array.length lines2 - 1 do
if (not used1.(i)) && (not used2.(j)) && distances.(i).(j) < !min_dist
then (
min_dist := distances.(i).(j);
min_i := i;
min_j := j)
done
done;

if !min_i <> -1 && !min_j <> -1 then (
paired := (!min_i, !min_j) :: !paired;
used1.(!min_i) <- true;
used2.(!min_j) <- true)
done;

let final_pairs = ref !paired in
for i = 0 to Array.length lines1 - 1 do
if not used1.(i) then final_pairs := (i, -1) :: !final_pairs
done;
for j = 0 to Array.length lines2 - 1 do
if not used2.(j) then final_pairs := (-1, j) :: !final_pairs
done;

List.sort compare !final_pairs

let compute (block : string Block.t) : line_content Block.t =
match block with
| Block.Common line -> Block.Common [ Unchanged line ]
| Block.Changed { mine; their; order } ->
let mine_array = Array.of_list mine in
let their_array = Array.of_list their in
let pairs = pair_lines mine_array their_array in

let result_mine = ref [] in
let result_their = ref [] in

List.iter
(fun (i, j) ->
match (i, j) with
| -1, j ->
let their_content = their_array.(j) in
result_their :=
(diff_words "" their_content |> snd) :: !result_their
| i, -1 ->
let mine_content = mine_array.(i) in
result_mine := (diff_words mine_content "" |> fst) :: !result_mine
| i, j ->
let mine_content = mine_array.(i) in
let their_content = their_array.(j) in
let mine_diff, their_diff =
diff_words mine_content their_content
in
result_mine := mine_diff :: !result_mine;
result_their := their_diff :: !result_their)
pairs;

Block.Changed
{ mine = List.rev !result_mine; their = List.rev !result_their; order }
let mine_str = String.concat " " mine in
let their_str = String.concat " " their in
let mine_words, their_words = diff_words mine_str their_str in
Block.Changed { mine = [ mine_words ]; their = [ their_words ]; order }
1 change: 0 additions & 1 deletion lib/WordDiff.mli
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ val compute : string Block.t -> line_content Block.t
(* for tests *)
val lcs : 'a list -> 'a list -> 'a list
val diff_words : string -> string -> line_content * line_content
val edit_distance : ('a -> 'a -> bool) -> 'a array -> 'a array -> int
20 changes: 10 additions & 10 deletions test/cram/test.t
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ This is a cram test for the new executable.
2 2
3 3 let main () =
4 - Interactive_viewer.start ()
4 + let s = In_channel.input_all In_channel.stdin in
5 + let patch = Patch.to_diffs s in
6 + Interactive_viewer.start patch
5 7
6 8 open Cmdliner
7 9
4 + let s = In_channel.input_all In_channel.stdin in let patch = Patch.to_diffs s in Interactive_viewer.start patch
5 5
6 6 open Cmdliner
7 7





Expand Down Expand Up @@ -91,8 +91,8 @@ This is a cram test for the new executable.
Modification of file.txt
@@ -2,1 +2,2 @@
1 - Hi everyone!
1 + This is the diffcessible project.
2 + Hello World!
1 + Hello World! This is the diffcessible project.




Expand All @@ -112,8 +112,8 @@ This is a cram test for the new executable.
Modification of file.txt
@@ -3,1 +5,2 @@
1 - This file starts at line 3.
1 + This is the second test case in this file.
2 + This file starts at line 5.
1 + This file starts at line 5. This is the second test case in this file.




Expand Down
53 changes: 1 addition & 52 deletions test/unit/TestWordDiff.ml
Original file line number Diff line number Diff line change
Expand Up @@ -121,56 +121,6 @@ let test_diff_words () =
List.iter test_case
[ test_diff_1; test_diff_2; test_diff_3; test_diff_4; test_diff_5 ]

let test_edit_distance_1 =
( [| 'k'; 'i'; 't'; 't'; 'e'; 'n' |],
[| 's'; 'i'; 't'; 't'; 'i'; 'n'; 'g' |],
3 )

let test_edit_distance_2 =
( [| 'S'; 'u'; 'n'; 'd'; 'a'; 'y' |],
[| 'S'; 'a'; 't'; 'u'; 'r'; 'd'; 'a'; 'y' |],
3 )

let test_edit_distance_3 = ([| 'a'; 'b'; 'c' |], [| 'a'; 'b'; 'c' |], 0)
let test_edit_distance_4 = ([| 'a'; 'b'; 'c' |], [| 'd'; 'e'; 'f' |], 3)
let test_edit_distance_5 = ([||], [| 'a'; 'b'; 'c' |], 3)
let test_edit_distance_6 = ([| 'a'; 'b'; 'c' |], [||], 3)
let test_edit_distance_7 = ([||], [||], 0) (* Both empty *)
let test_edit_distance_8 = ([| 'a' |], [| 'b' |], 1)
let test_edit_distance_9 = ([| 'a'; 'a'; 'a' |], [| 'a'; 'a'; 'a'; 'a' |], 1)
let test_edit_distance_10 = ([| 'a'; 'a'; 'a'; 'a' |], [| 'a'; 'a'; 'a' |], 1)
let test_edit_distance_11 = ([| '1'; '2'; '3' |], [| '2'; '3'; '4' |], 2)
(* Shift *)

let test_edit_distance_12 =
([| 'a'; 'b'; 'c'; 'd'; 'e'; 'f' |], [| 'a'; 'z'; 'c'; 'd'; 'e'; 'f' |], 1)

let test_edit_distance () =
let test_case (input1, input2, expected) =
let result = WordDiff.edit_distance Char.equal input1 input2 in
assert_with_message (result = expected)
(Printf.sprintf
"edit_distance failed\nInput1: %s\nInput2: %s\nExpected: %d\nGot: %d"
(String.of_seq (Array.to_seq input1))
(String.of_seq (Array.to_seq input2))
expected result)
in
List.iter test_case
[
test_edit_distance_1;
test_edit_distance_2;
test_edit_distance_3;
test_edit_distance_4;
test_edit_distance_5;
test_edit_distance_6;
test_edit_distance_7;
test_edit_distance_8;
test_edit_distance_9;
test_edit_distance_10;
test_edit_distance_11;
test_edit_distance_12;
]

(* Updated run_tests function *)
let run_tests () =
let run_test name f =
Expand All @@ -185,7 +135,6 @@ let run_tests () =
(Printexc.to_string exn)
in
run_test "test_lcs" test_lcs;
run_test "test_diff_words" test_diff_words;
run_test "test_edit_distance" test_edit_distance
run_test "test_diff_words" test_diff_words

let () = run_tests ()

0 comments on commit 758019a

Please sign in to comment.