@@ -5,6 +5,11 @@ import "sync"
55// FreqMap records the frequency of each rune in a given text.
66type FreqMap map [rune ]int
77
8+ type runeCount struct {
9+ r rune
10+ c int
11+ }
12+
813// Frequency counts the frequency of each rune in a given text and returns this
914// data as a FreqMap.
1015func Frequency (s string ) FreqMap {
@@ -17,35 +22,41 @@ func Frequency(s string) FreqMap {
1722
1823// ConcurrentFrequency counts the frequency of each rune in parallel.
1924func ConcurrentFrequency (strings []string ) FreqMap {
20- var wg sync.WaitGroup
21- sc := safeCounter {}
22- sc .v = make (FreqMap )
25+ var runeCounterChan = make ([]chan runeCount , len (strings ))
2326
24- for _ , s := range strings {
25- wg . Add ( 1 )
26- go func (str string ) {
27+ for i , s := range strings {
28+ runeCounterChan [ i ] = make ( chan runeCount , 25 )
29+ go func (str string , runeCounterChan chan runeCount ) {
2730 smap := Frequency (str )
2831 for r , c := range smap {
29- sc . Add ( r , c )
32+ runeCounterChan <- runeCount { r : r , c : c }
3033 }
31- defer wg . Done ( )
32- }(s )
34+ close ( runeCounterChan )
35+ }(s , runeCounterChan [ i ] )
3336 }
3437
35- wg .Wait ()
38+ var wg sync.WaitGroup
39+ var merged = make (chan runeCount , 100 )
40+ for i := range strings {
41+ wg .Add (1 )
42+ go func (i int ) {
43+ for rc := range runeCounterChan [i ] {
44+ merged <- rc
45+ }
46+ defer wg .Done ()
47+ }(i )
48+ }
3649
37- return sc .v
38- }
50+ go func () {
51+ wg .Wait ()
52+ close (merged )
53+ }()
3954
40- type safeCounter struct {
41- v FreqMap
42- mux sync.Mutex
43- }
55+ fm := FreqMap {}
56+ for rc := range merged {
57+ // Process each value
58+ fm [rc .r ] += rc .c
59+ }
4460
45- // Add increases the value for the counter for the given key.
46- func (c * safeCounter ) Add (key rune , count int ) {
47- c .mux .Lock ()
48- // Lock so only one goroutine at a time can access the map c.v.
49- c .v [key ] += count
50- c .mux .Unlock ()
61+ return fm
5162}
0 commit comments