package main import ( "flag" "fmt" "github.com/dariubs/percent" "gonum.org/v1/plot" "gonum.org/v1/plot/plotter" "gonum.org/v1/plot/plotutil" "gonum.org/v1/plot/vg" "log" "os" "sort" "strings" ) type letter struct { upperCase string lowerCase string count int frequency float64 } type letterList []letter func (l letterList) Len() int { return len(l) } func (l letterList) Less(firstIndex, secondIndex int) bool { return l[firstIndex].frequency > l[secondIndex].frequency } func (l letterList) Swap(firstIndex, secondIndex int) { l[firstIndex], l[secondIndex] = l[secondIndex], l[firstIndex] } const lettersInTheAlphabet = 'Z' - 'A' + 1 var letters = make([]letter, lettersInTheAlphabet) func init() { for i := 0; i < lettersInTheAlphabet; i++ { letters[i].upperCase = string(rune('A' + i)) letters[i].lowerCase = string(rune('A' + i + 32)) } } func parseArguments() string { var inputFile string flag.StringVar(&inputFile, "f", "", "Specify file to analyse.") flag.Parse() if inputFile == "" { log.Print("No flag provided\n\nHelp:\n") flag.PrintDefaults() os.Exit(1) } return inputFile } func readFile(relativePath string) string { content, err := os.ReadFile(relativePath) if err != nil { log.Fatalln(err) } return string(content) } func countLetters(inputText string) int { totalCount := 0 for i := 0; i < lettersInTheAlphabet; i++ { letters[i].count += strings.Count(inputText, letters[i].lowerCase) + strings.Count(inputText, letters[i].upperCase) totalCount += letters[i].count } return totalCount } func calculateFrequency(totalCount int) { for i := 0; i < lettersInTheAlphabet; i++ { letters[i].frequency = percent.PercentOf(letters[i].count, totalCount) } } func printResult() { for i := 0; i < lettersInTheAlphabet; i++ { l := letters[i] fmt.Printf( "The letter %s (%s) occurs %d times in the text and the frequencyArray in percent is %0.2f\n", l.upperCase, l.lowerCase, l.count, l.frequency, ) } } func plotResult() { var count plotter.Values for i := 0; i < lettersInTheAlphabet; i++ { count = append(count, float64(letters[i].count)) } p := plot.New() p.Title.Text = "Letter count" p.X.Label.Text = "letter" p.Y.Label.Text = "count" countBars, err := plotter.NewBarChart(count, vg.Points(lettersInTheAlphabet/2)) countBars.Color = plotutil.Color(2) if err != nil { log.Fatalln(err) } p.Add(countBars) var xAxisNaming []string for index := range letters { xAxisNaming = append(xAxisNaming, letters[index].upperCase) } p.NominalX(xAxisNaming...) if err = p.Save(25*vg.Centimeter, 15*vg.Centimeter, "barChart.png"); err != nil { log.Fatalln(err) } } func main() { inputFile := parseArguments() totalCount := countLetters(readFile(inputFile)) calculateFrequency(totalCount) plotResult() sort.Sort(letterList(letters)) printResult() }