diff --git a/hw03_frequency_analysis/.sync b/hw03_frequency_analysis/.sync deleted file mode 100644 index e69de29..0000000 diff --git a/hw03_frequency_analysis/go.mod b/hw03_frequency_analysis/go.mod index 8fe087f..b67c12d 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/DimVlas/otus_hw/hw03_frequency_analysis go 1.19 diff --git a/hw03_frequency_analysis/top.go b/hw03_frequency_analysis/top.go index aff6568..6e17769 100644 --- a/hw03_frequency_analysis/top.go +++ b/hw03_frequency_analysis/top.go @@ -1,6 +1,77 @@ package hw03frequencyanalysis -func Top10(_ string) []string { - // Place your code here. - return nil +import ( + "fmt" + "sort" + "strings" +) + +// Разбивает текст на слова, возвращает срез слов. +func GetWords(text string) []string { + if len(text) < 1 { + return []string{} + } + + return strings.Fields(text) +} + +// Считает частоту элементов в строковом срезе. +// Возвращает map, где key элемент среза, +// а value сколько раз встречался элемент. +func CountOfElements(s []string) map[string]int { + m := make(map[string]int) + + for _, w := range s { + if cnt, ok := m[w]; ok { + cnt++ + m[w] = cnt + } else { + m[w] = 1 + } + } + return m +} + +type wordWidth struct { + Word string + Width int +} + +func (w wordWidth) GetKey() string { + return fmt.Sprintf("%04d%s", w.Width, w.Word) +} + +func Top10(text string) []string { + if len(text) < 1 { + return []string{} + } + + words := GetWords(text) + if len(words) < 1 { + return []string{} + } + + countMap := CountOfElements(words) + countWords := make([]wordWidth, 0, len(countMap)) + + for k, v := range countMap { + countWords = append(countWords, wordWidth{Word: k, Width: v}) + } + + sort.Slice(countWords, func(i, j int) bool { + return countWords[i].Width > countWords[j].Width || + (countWords[i].Width == countWords[j].Width && countWords[i].Word < countWords[j].Word) + }) + + res := make([]string, 0, 10) + + ln := len(countWords) + if ln > 10 { + ln = 10 + } + + for _, ww := range countWords[:ln] { + res = append(res, ww.Word) + } + return res } diff --git a/hw03_frequency_analysis/top_test.go b/hw03_frequency_analysis/top_test.go index e28c5cb..684559d 100644 --- a/hw03_frequency_analysis/top_test.go +++ b/hw03_frequency_analysis/top_test.go @@ -80,3 +80,79 @@ func TestTop10(t *testing.T) { } }) } + +func TestGetWords(t *testing.T) { + tests := []struct { + input string + expected []string + }{ + {input: "", expected: []string{}}, + {input: "alfa beta gamma ", expected: []string{"alfa", "beta", "gamma"}}, + { + input: `Предложения складываются в абзацы — + и вы наслаждетесь очередным бредошедевром.`, + expected: []string{ + "Предложения", + "складываются", + "в", + "абзацы", + "—", + "и", + "вы", + "наслаждетесь", + "очередным", + "бредошедевром.", + }, + }, + } + + for _, tc := range tests { + tc := tc + t.Run(tc.input, func(t *testing.T) { + result := GetWords(tc.input) + require.Equal(t, tc.expected, result) + }) + } +} + +func TestCountOfElements(t *testing.T) { + tests := []struct { + name string + input []string + expected map[string]int + }{ + { + name: "empty", + input: []string{}, + expected: map[string]int{}, + }, + { + name: "all_one", + input: []string{"alfa", "beta", "gamma"}, + expected: map[string]int{ + "alfa": 1, + "beta": 1, + "gamma": 1, + }, + }, + { + name: "second_two", + input: []string{"Мама", "мыла", "раму,", "раму", "мыла", "мама"}, + expected: map[string]int{ + "Мама": 1, + "мыла": 2, + "раму,": 1, + "раму": 1, + "мама": 1, + }, + }, + } + + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + result := CountOfElements(tc.input) + require.Equal(t, tc.expected, result) + }) + } +}