I am trying to print vowel count from a text file. I am not getting the expected count. I can do this using a regular approach of just counting the character count using strings.Count(). But I want to use concurrency to see how it works. This is the link to text file -> "https://www.gutenberg.org/cache/epub/2600/pg2600.txt"
File size -> 3.36 MB
Below is my code.
Any help is appreciated.
Result I am getting using below code:
A - 145310 E - 188280 I - 116195 O - 131900 U - 47560
Expected result :
A - 202712 E - 313609 I - 172232 O - 190103 U - 64401
package main
import (
"bufio"
"fmt"
"io"
"os"
"strings"
"sync"
)
const mb = 1024 * 1024
func main() {
aCount, eCount, iCount, oCount, uCount := 0, 0, 0, 0, 0
wg := &sync.WaitGroup{}
channel := make(chan (string))
done := make(chan (bool), 1)
go func() {
for s := range channel {
if strings.Contains(strings.ToUpper(s), "A") {
aCount++
}
if strings.Contains(strings.ToUpper(s), "E") {
eCount++
}
if strings.Contains(strings.ToUpper(s), "I") {
iCount++
}
if strings.Contains(strings.ToUpper(s), "O") {
oCount++
}
if strings.Contains(strings.ToUpper(s), "U") {
uCount++
}
}
done <- true
}()
var current int64
var limit int64 = 0.5 * mb
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
read(current, limit, "interview.txt", channel)
fmt.Printf("%d thread has been completed", i)
wg.Done()
}()
current += limit + 1
}
// Wait for all go routines to complete.
wg.Wait()
close(channel)
<-done
close(done)
fmt.Println("A - ", aCount)
fmt.Println("E - ", eCount)
fmt.Println("I - ", iCount)
fmt.Println("O - ", oCount)
fmt.Println("U - ", uCount)
}
func read(offset int64, limit int64, fileName string, channel chan (string)) {
file, err := os.Open(fileName)
defer file.Close()
if err != nil {
panic(err)
}
file.Seek(offset, 0)
reader := bufio.NewReader(file)
if offset != 0 {
_, err = reader.ReadBytes(' ')
if err == io.EOF {
fmt.Println("EOF")
return
}
if err != nil {
panic(err)
}
}
var cummulativeSize int64
for {
// Break if read size has exceed the chunk size.
if cummulativeSize > limit {
break
}
b, err := reader.ReadBytes(' ')
// Break if end of file is encountered.
if err == io.EOF {
break
}
if err != nil {
panic(err)
}
cummulativeSize += int64(len(b))
s := strings.TrimSpace(string(b))
if s != "" {
channel <- s
}
}
}