From 0d02625c3f24e6bea0ad2f2c33c3b6746fdee988 Mon Sep 17 00:00:00 2001 From: Abi Rafdi Date: Wed, 11 Mar 2020 12:11:05 +0700 Subject: [PATCH] change diff score from 1 to custom variable --- lib/simetric/levenshtein.ex | 30 +++++++++++++++--------------- test/simetric/levenshtein_test.exs | 24 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/lib/simetric/levenshtein.ex b/lib/simetric/levenshtein.ex index 8908680..c6e2afe 100644 --- a/lib/simetric/levenshtein.ex +++ b/lib/simetric/levenshtein.ex @@ -14,33 +14,33 @@ defmodule Simetric.Levenshtein do 3 """ - @spec compare(String.t, String.t) :: non_neg_integer - def compare(string1, string2) + @spec compare(String.t, String.t, integer) :: non_neg_integer + def compare(string1, string2, diff_score \\ 1) - def compare(string, string), do: 0 + def compare(string, string, _), do: 0 - def compare(string1, ""), do: String.length(string1) + def compare(string1, "", _), do: String.length(string1) - def compare("", string2), do: String.length(string2) + def compare("", string2, _), do: String.length(string2) - def compare(string1, string2) do + def compare(string1, string2, diff_score) do chars1 = String.graphemes(string1) chars2 = String.graphemes(string2) - distance(chars1, chars2, length(chars2)..0, 1) + distance(chars1, chars2, length(chars2)..0, 1, diff_score) end - defp distance([], _, [result | _], _), do: result + defp distance([], _, [result | _], _, _), do: result - defp distance([char | rest], chars2, distlist, step) do - distlist = proceed(char, chars2, Enum.reverse(distlist), [step], step) - distance(rest, chars2, distlist, step + 1) + defp distance([char | rest], chars2, distlist, step, diff_score) do + distlist = proceed(char, chars2, Enum.reverse(distlist), [step], step, diff_score) + distance(rest, chars2, distlist, step + 1, diff_score) end - defp proceed(_, [], _, acc, _), do: acc + defp proceed(_, [], _, acc, _, _), do: acc - defp proceed(char1, [char2 | rest], [head | [prev | _] = distlist], acc, score) do - diff = if char1 == char2, do: 0, else: 1 + defp proceed(char1, [char2 | rest], [head | [prev | _] = distlist], acc, score, diff_score) do + diff = if char1 == char2, do: 0, else: diff_score score = min(min(score + 1, prev + 1), head + diff) - proceed(char1, rest, distlist, [score | acc], score) + proceed(char1, rest, distlist, [score | acc], score, diff_score) end end diff --git a/test/simetric/levenshtein_test.exs b/test/simetric/levenshtein_test.exs index 31c564c..1de6231 100644 --- a/test/simetric/levenshtein_test.exs +++ b/test/simetric/levenshtein_test.exs @@ -33,9 +33,33 @@ defmodule Simetric.LevenshteinTest do ["distance", "difference"] => 5 } + cases_custom = %{ + # empty strings + ["", ""] => 0, + ["", "ab"] => 2, + ["abc", ""] => 3, + # equal strings + ["abc", "abc"] => 0, + # inserts only + ["ac", "abc"] => 1, + # deletions only + ["xabxcdxxefxgx", "abcdefg"] => 6, + # substitutions only + ["a", "b"] => 2, + ["xabxcdxxefxgx", "1ab2cd34ef5g6"] => 12, + # mixed operations + ["levenshtein", "frankenstein"] => 9 + } + for {input, distance} <- cases do test "compare #{inspect input}" do assert Simetric.Levenshtein.compare(unquote_splicing(input)) == unquote(distance) end end + + for {input, distance} <- cases_custom do + test "compare custom #{inspect input} with diff_distance = 2" do + assert Simetric.Levenshtein.compare(unquote_splicing(input), 2) == unquote(distance) + end + end end