package linguistics import ( "strings" ) // PhoneticEncoder encodes words phonetically type PhoneticEncoder struct{} // NewPhoneticEncoder creates a new PhoneticEncoder func NewPhoneticEncoder() *PhoneticEncoder { return &PhoneticEncoder{} } // Encode encodes a word phonetically and returns the encoding // //nolint:gocyclo // Complex encoding rules func (e *PhoneticEncoder) Encode(word string) string { // This is a simplified implementation of the Soundex algorithm // In a real-world scenario, you would use a library like github.com/jdkato/prose // or call an external API for phonetic encoding // Convert to uppercase word = strings.ToUpper(word) // Remove non-alphabetic characters var sb strings.Builder for _, r := range word { if r >= 'A' && r <= 'Z' { sb.WriteRune(r) } } word = sb.String() // Return empty string for empty input if len(word) == 0 { return "" } // Keep the first letter result := string(word[0]) // Map consonants to digits for i := 1; i < len(word); i++ { c := word[i] var code byte switch c { case 'B', 'F', 'P', 'V': code = '1' case 'C', 'G', 'J', 'K', 'Q', 'S', 'X', 'Z': code = '2' case 'D', 'T': code = '3' case 'L': code = '4' case 'M', 'N': code = '5' case 'R': code = '6' default: code = '0' // Vowels and 'H', 'W', 'Y' } // Skip vowels and 'H', 'W', 'Y' if code == '0' { continue } // Skip duplicates if i > 1 && code == result[len(result)-1] { continue } result += string(code) // Limit to 4 characters if len(result) >= 4 { break } } // Pad with zeros if necessary for len(result) < 4 { result += "0" } return result } // DoubleMetaphone is an alternative phonetic algorithm func (e *PhoneticEncoder) DoubleMetaphone(word string) (string, string) { // This is a simplified implementation of the Double Metaphone algorithm // In a real-world scenario, you would use a library or call an external API // For simplicity, we'll just return the Soundex code and a variation soundex := e.Encode(word) // Create a variation by replacing the first digit with the next digit var variation string if len(soundex) > 1 { firstDigit := soundex[1] var nextDigit byte if firstDigit >= '6' { nextDigit = '1' } else { nextDigit = firstDigit + 1 } variation = string(soundex[0]) + string(nextDigit) + soundex[2:] } else { variation = soundex } return soundex, variation }