99 lines
1.9 KiB
Go
99 lines
1.9 KiB
Go
package bastion_init
|
|
|
|
import (
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
type WordC struct {
|
|
Word string
|
|
Rank int
|
|
}
|
|
|
|
func normalize(s string) string {
|
|
// Convert to lowercase and replace hyphens with underscores for consistent comparison.
|
|
return strings.Map(func(r rune) rune {
|
|
if 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' {
|
|
return r
|
|
}
|
|
return '_'
|
|
}, s)
|
|
}
|
|
|
|
func levDpDist(s1, s2 string) int {
|
|
m, n := len(s1), len(s2)
|
|
if m == 0 {
|
|
return n
|
|
}
|
|
if n == 0 {
|
|
return m
|
|
}
|
|
|
|
dp := make([][]int, m+1)
|
|
for i := range dp {
|
|
dp[i] = make([]int, n+1)
|
|
}
|
|
|
|
for i := 1; i <= m; i++ {
|
|
for j := 1; j <= n; j++ {
|
|
cost := 0
|
|
if s1[i-1] != s2[j-1] {
|
|
cost = 1
|
|
}
|
|
dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1]) + cost
|
|
}
|
|
}
|
|
return dp[m][n]
|
|
}
|
|
|
|
func min(a, b, c int) int {
|
|
minVal := a
|
|
if b < minVal {
|
|
minVal = b
|
|
}
|
|
if c < minVal {
|
|
minVal = c
|
|
}
|
|
return minVal
|
|
}
|
|
|
|
func FindClosestWordDp(words []string, prefix string) (string, error) {
|
|
normalizedPrefix := normalize(prefix)
|
|
normalizedWords := make([]string, len(words))
|
|
for i, word := range words {
|
|
normalizedWords[i] = normalize(word)
|
|
}
|
|
|
|
sort.Slice(normalizedWords, func(i, j int) bool {
|
|
return normalizedWords[i] < normalizedWords[j]
|
|
})
|
|
|
|
minDistance := levDpDist(normalizedPrefix, normalizedWords[0])
|
|
closestWord := normalizedWords[0]
|
|
|
|
for _, word := range normalizedWords {
|
|
distance := levDpDist(normalizedPrefix, word)
|
|
if distance < minDistance {
|
|
minDistance = distance
|
|
closestWord = word
|
|
}
|
|
}
|
|
|
|
// Replace underscores with hyphens and convert back to original case.
|
|
closestWord = strings.ReplaceAll(strings.ReplaceAll(strings.ToUpper(closestWord), "_", "-"), "\"", "")
|
|
return closestWord, nil
|
|
}
|
|
|
|
func main() {
|
|
words := []string{"Apple", "Apricot", "Apprentice", "Application"}
|
|
prefix := "AP"
|
|
|
|
closest, err := FindClosestWordDp(words, prefix)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
} else {
|
|
fmt.Printf("The closest word to '%s' is '%s'\n", prefix, closest)
|
|
}
|
|
}
|