diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8b236e3 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.hafen.run/lukas/edit-distance + +go 1.18 diff --git a/helpers.go b/helpers.go new file mode 100644 index 0000000..dec8b86 --- /dev/null +++ b/helpers.go @@ -0,0 +1,11 @@ +package editdistance + +func min(nums ...int) int { + min := nums[0] + for _, v := range nums { + if v < min { + min = v + } + } + return min +} diff --git a/helpers_test.go b/helpers_test.go new file mode 100644 index 0000000..d4cd8bb --- /dev/null +++ b/helpers_test.go @@ -0,0 +1,10 @@ +package editdistance + +import "testing" + +func TestMin(t *testing.T) { + mins := min(1, 2, 3, 4, 5) + if mins != 1 { + t.Errorf("Min was incorrect, got %d, want %d.", mins, 1) + } +} diff --git a/wagner-fisher.go b/wagner-fisher.go new file mode 100644 index 0000000..6c021e0 --- /dev/null +++ b/wagner-fisher.go @@ -0,0 +1,14 @@ +package editdistance + +func WagnerFisher(a, b string) int { + if len(a) == 0 { + return len(b) + } + if len(b) == 0 { + return len(a) + } + if a[0] == b[0] { + return WagnerFisher(a[1:], b[1:]) + } + return 1 + min(WagnerFisher(a[1:], b), WagnerFisher(a, b[1:]), WagnerFisher(a[1:], b[1:])) +} diff --git a/wagner-fisher_test.go b/wagner-fisher_test.go new file mode 100644 index 0000000..dba8c83 --- /dev/null +++ b/wagner-fisher_test.go @@ -0,0 +1,11 @@ +package editdistance + +import "testing" + +func TestWagnerFisher(t *testing.T) { + a := "abc" + b := "abd" + if WagnerFisher(a, b) != 1 { + t.Errorf("WagnerFisher was incorrect, got %d, want %d.", WagnerFisher(a, b), 1) + } +} diff --git a/werner.go b/werner.go new file mode 100644 index 0000000..c76591a --- /dev/null +++ b/werner.go @@ -0,0 +1,45 @@ +package editdistance + +import ( + "strings" +) + +func Werner(a, b string) int { + + phrase_a := strings.Fields(a) + phrase_b := strings.Fields(b) + + m := len(phrase_a) + 1 + n := len(phrase_b) + 1 + distances := make([][]int, n) + for i := range distances { + distances[i] = make([]int, m) + } + // make the inital numbers on the top + for i := 1; i < n; i++ { + distances[i][0] = i + } + // make the inital numbers on the left side + for i := 1; i < m; i++ { + distances[0][i] = i + } + + for i := 1; i < n; i++ { + for j := 1; j < m; j++ { + subCost := 0 + if strings.EqualFold(phrase_a[j-1], phrase_b[i-1]) { + subCost = 0 + } else { + subCost = 1 + } + value := min( + distances[i-1][j]+1, + distances[i][j-1]+1, + distances[i-1][j-1]+subCost, + ) + distances[i][j] = value + } + } + + return distances[n-1][m-1] +} diff --git a/werner_test.go b/werner_test.go new file mode 100644 index 0000000..279ba9e --- /dev/null +++ b/werner_test.go @@ -0,0 +1,20 @@ +package editdistance + +import "testing" + +func TestWerner(t *testing.T) { + + a := "a b c" + b := "a b d" + diff := Werner(a, b) + if diff != 1 { + t.Errorf("Werner was incorrect, got %d, want %d.", diff, 1) + } + + a = "Mary had a little lamb little lamb little lamb." + b = "Marry had a little lamb little lab little lamb." + diff = Werner(a, b) + if diff != 2 { + t.Errorf("Werner was incorrect, got %d, want %d.", diff, 2) + } +}