mirror of
https://github.com/MichaelMure/git-bug.git
synced 2024-12-15 18:23:08 +03:00
b478cd1bcb
fix #6
72 lines
1.6 KiB
Go
72 lines
1.6 KiB
Go
// Package levenshtein is a Go implementation to calculate Levenshtein Distance.
|
|
//
|
|
// Implementation taken from
|
|
// https://gist.github.com/andrei-m/982927#gistcomment-1931258
|
|
package levenshtein
|
|
|
|
// ComputeDistance computes the levenshtein distance between the two
|
|
// strings passed as an argument. The return value is the levenshtein distance
|
|
//
|
|
// Works on runes (Unicode code points) but does not normalize
|
|
// the input strings. See https://blog.golang.org/normalization
|
|
// and the golang.org/x/text/unicode/norm pacage.
|
|
func ComputeDistance(a, b string) int {
|
|
if a == b {
|
|
return 0
|
|
}
|
|
|
|
// We need to convert to []rune if the strings are non-ascii.
|
|
// This could be avoided by using utf8.RuneCountInString
|
|
// and then doing some juggling with rune indices.
|
|
// The primary challenge is keeping track of the previous rune.
|
|
// With a range loop, its not that easy. And with a for-loop
|
|
// we need to keep track of the inter-rune width using utf8.DecodeRuneInString
|
|
s1 := []rune(a)
|
|
s2 := []rune(b)
|
|
|
|
// swap to save some memory O(min(a,b)) instead of O(a)
|
|
if len(s1) > len(s2) {
|
|
s1, s2 = s2, s1
|
|
}
|
|
lenS1 := len(s1)
|
|
lenS2 := len(s2)
|
|
|
|
// init the row
|
|
x := make([]int, lenS1+1)
|
|
for i := 0; i <= lenS1; i++ {
|
|
x[i] = i
|
|
}
|
|
|
|
// fill in the rest
|
|
for i := 1; i <= lenS2; i++ {
|
|
prev := i
|
|
var current int
|
|
|
|
for j := 1; j <= lenS1; j++ {
|
|
|
|
if s2[i-1] == s1[j-1] {
|
|
current = x[j-1] // match
|
|
} else {
|
|
current = min(x[j-1]+1, prev+1, x[j]+1)
|
|
}
|
|
x[j-1] = prev
|
|
prev = current
|
|
}
|
|
x[lenS1] = prev
|
|
}
|
|
return x[lenS1]
|
|
}
|
|
|
|
func min(a, b, c int) int {
|
|
if a < b {
|
|
if a < c {
|
|
return a
|
|
}
|
|
} else {
|
|
if b < c {
|
|
return b
|
|
}
|
|
}
|
|
return c
|
|
}
|