diff --git a/hw03_frequency_analysis/go.mod b/hw03_frequency_analysis/go.mod index 1ff43eb..2b6e981 100644 --- a/hw03_frequency_analysis/go.mod +++ b/hw03_frequency_analysis/go.mod @@ -1,4 +1,4 @@ -module github.com/fixme_my_friend/hw03_frequency_analysis +module github.com/ezhk/golang-learning/hw03_frequency_analysis go 1.14 diff --git a/hw03_frequency_analysis/top.go b/hw03_frequency_analysis/top.go index 7cd719b..29cb5e8 100644 --- a/hw03_frequency_analysis/top.go +++ b/hw03_frequency_analysis/top.go @@ -1,6 +1,50 @@ package hw03_frequency_analysis //nolint:golint,stylecheck -func Top10(_ string) []string { - // Place your code here - return nil +import ( + "regexp" + "sort" + "strings" + "unicode" +) + +var ignoredSymbols = regexp.MustCompile(`[-]`) + +type WordFrequency struct { + word string + RepeatCounter int +} + +func Top10(inputLine string) []string { + const MaxLength = 10 + mostFrequentWords := make([]string, 0, MaxLength) + + // prepare map with counter + freqMap := make(map[string]int) + inputLine = ignoredSymbols.ReplaceAllString(inputLine, "") + for _, word := range strings.FieldsFunc(inputLine, splitFunc) { + freqMap[strings.ToLower(word)]++ + } + + // convert map to slice wordFrequency for next sorting + wordSlice := make([]WordFrequency, 0, len(freqMap)) + for word, counter := range freqMap { + wordSlice = append(wordSlice, WordFrequency{word, counter}) + } + sort.Slice(wordSlice, func(i, j int) bool { + return wordSlice[i].RepeatCounter > wordSlice[j].RepeatCounter + }) + + // store data + for _, value := range wordSlice { + if len(mostFrequentWords) >= MaxLength { + break + } + mostFrequentWords = append(mostFrequentWords, value.word) + } + + return mostFrequentWords +} + +func splitFunc(char rune) bool { + return unicode.IsPunct(char) || unicode.IsSpace(char) } diff --git a/hw03_frequency_analysis/top_test.go b/hw03_frequency_analysis/top_test.go index 6ceef08..03830c4 100644 --- a/hw03_frequency_analysis/top_test.go +++ b/hw03_frequency_analysis/top_test.go @@ -7,7 +7,7 @@ import ( ) // Change to true if needed -var taskWithAsteriskIsCompleted = false +var taskWithAsteriskIsCompleted = true var text = `Как видите, он спускается по лестнице вслед за своим другом Кристофером Робином, головой вниз, пересчитывая @@ -58,3 +58,26 @@ func TestTop10(t *testing.T) { } }) } + +func TestExtendedTop10(t *testing.T) { + type test struct { + text string + expected []string + } + for _, testCase := range []test{ + {"какой-то", []string{"какойто"}}, + {"кот,собака собака", []string{"собака", "кот"}}, + // check ingoring "-" in next test + {"12 1-2 5", []string{"12", "5"}}, + {"1\n, ;1 -1 \t2,2 3.", []string{"1", "2", "3"}}, + } { + result := Top10(testCase.text) + assert.Equal(t, result, testCase.expected) + } +} + +func BenchmarkTop(b *testing.B) { + for i := 0; i < b.N; i++ { + Top10(text) + } +}