The task is for training go-lang. The idea is to extract unique words sorted and grouped by length. Might be useful in learning new words. The program uses command line argument assuming it's a file to read; reads from stdin if no arguments were given.
package main
import (
"bufio"
"fmt"
"os"
"regexp"
"sort"
"strings"
)
type words = map[string]struct{}
type groupedWords = map[int]words
// Checks for fatal errors.
// If non nil error passed program will be terminated
func check(e error) {
if e != nil {
panic(e)
}
}
// Reads data from bufio.Reader and returns
// a map of grouped unique words: key is letters count, value is map of words
func getGroupedWords(reader *bufio.Reader) groupedWords {
groupedWords := make(groupedWords)
re, err := regexp.Compile("[^a-zA-Z]")
check(err)
for {
str, err := reader.ReadString(' ')
str = strings.ToLower(strings.TrimSpace(str))
if !re.MatchString(str) {
val, exists := groupedWords[len(str)]
if !exists {
groupedWords[len(str)] = words{str: struct{}{}}
} else {
val[str] = struct{}{}
}
}
if err != nil {
break
}
}
delete(groupedWords, 0)
return groupedWords
}
// Extracts sorted slice of keys from words
func getSortedKeysWord(w words) []string {
list := make([]string, len(w))
i := 0
for word := range w {
list[i] = word
i++
}
sort.Strings(list)
return list
}
// Extracts sorted slice of letters count from groupedWords
func getSortedKeysGroupedWord(gw groupedWords) []int {
list := make([]int, len(gw))
i := 0
for lettersCnt := range gw {
list[i] = lettersCnt
i++
}
sort.Ints(list)
return list
}
func main() {
var reader *bufio.Reader
args := os.Args
if len(args) == 1 {
reader = bufio.NewReader(os.Stdin)
} else {
file, err := os.Open(args[1])
check(err)
reader = bufio.NewReader(file)
}
groupedWords := getGroupedWords(reader)
lettersCntList := getSortedKeysGroupedWord(groupedWords)
for _, lettersCnt := range lettersCntList {
list := getSortedKeysWord(groupedWords[lettersCnt])
fmt.Print(lettersCnt, "(", len(list), "):\t")
for _, word := range list {
fmt.Print(word, " ")
}
fmt.Println()
}
}
usage
echo "The unary notation can be abbreviated by introducing different symbols for certain new values. " | go run extract_words.go
should give
2(2): be by
3(3): can for new
5(1): unary
7(2): certain symbols
8(1): notation
9(1): different
11(2): abbreviated introducing