Skip to content

Instantly share code, notes, and snippets.

@barakplasma
Last active September 23, 2020 13:59
Show Gist options
  • Save barakplasma/ebcc68e924f3588ca84c0c728069d5de to your computer and use it in GitHub Desktop.
Save barakplasma/ebcc68e924f3588ca84c0c728069d5de to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
)
func main() {
fmt.Println(Divisors_simple(10)) // should equal 4
fmt.Println(Divisors_pointers(10)) // should equal 4
fmt.Println(Divisors_channels(10)) // should equal 4
}
// inspired by https://www.codewars.com/kata/542c0f198e077084c0000c2e/go
package main
import (
"fmt"
"sync"
)
func main() {
n := 100
fmt.Println("channels result: ", DivisorsChannels(n))
fmt.Println("pointer result: ", DivisorsPointers(n))
fmt.Println("simple result: ", DivisorsSimple(n))
}
// ## 1 ##
func check1(i int, n int, c chan int, wg *sync.WaitGroup) {
if n%i == 0 {
c <- 1 // <- is the "send" operator when a channel appears on the left.
}
wg.Done()
}
func monitorWorker(wg *sync.WaitGroup, c chan int) {
wg.Wait()
close(c)
}
// DivisorsChannels - using channels to share goroutine results
func DivisorsChannels(n int) int {
wg := &sync.WaitGroup{}
c := make(chan int, 4)
d := 1
for i := 1; i <= n/2; i++ {
wg.Add(1)
go check1(i, n, c, wg)
}
go monitorWorker(wg, c)
for o := range c {
d = d + o
}
return d
}
// ## 2 ##
func check2(i int, n int, d *int, wg *sync.WaitGroup) {
if n%i == 0 {
*d = *d + 1
}
wg.Done()
}
// DivisorsPointers - using pointers to share goroutine results
func DivisorsPointers(n int) int {
d := 1
wg := &sync.WaitGroup{}
for i := 1; i <= n/2; i++ {
wg.Add(1)
go check2(i, n, &d, wg)
}
wg.Wait()
return d
}
// DivisorsSimple - simple loop
func DivisorsSimple(n int) int {
d := 1
for i := 1; i <= n/2; i++ {
if n%i == 0 {
d++
}
}
return d
}
package main
import (
"testing"
)
/**
go test -benchmem -run=^$ -bench .
goos: darwin
goarch: amd64
BenchmarkDivisors_channels-12 607 1874624 ns/op 1314 B/op 5 allocs/op
BenchmarkDivisors_pointers-12 655 1863368 ns/op 187 B/op 2 allocs/op
BenchmarkDivisors_simple-12 20252 61944 ns/op 0 B/op 0 allocs/op
PASS
ok _/Users/smichael1/Documents/projects/Codewars 4.831s
*/
func BenchmarkDivisors_channels(b *testing.B) {
for n := 0; n < b.N; n++ {
DivisorsChannels(10000)
}
}
func TestDivisors_channels(t *testing.T) {
type args struct {
n int
}
tests := []struct {
name string
n int
want int
}{
{"small", 1, 1},
{"med", 100, 9},
{"large", 10000, 25},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := DivisorsChannels(tt.n); got != tt.want {
t.Errorf("DivisorsChannels() = %v, want %v", got, tt.want)
}
})
}
}
func BenchmarkDivisors_pointers(b *testing.B) {
for n := 0; n < b.N; n++ {
DivisorsPointers(10000)
}
}
func TestDivisors_pointers(t *testing.T) {
type args struct {
n int
}
tests := []struct {
name string
n int
want int
}{
{"small", 1, 1},
{"med", 100, 9},
{"large", 10000, 25},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := DivisorsPointers(tt.n); got != tt.want {
t.Errorf("DivisorsPointers() = %v, want %v", got, tt.want)
}
})
}
}
func BenchmarkDivisors_simple(b *testing.B) {
for n := 0; n < b.N; n++ {
DivisorsSimple(10000)
}
}
func TestDivisors_simple(t *testing.T) {
type args struct {
n int
}
tests := []struct {
name string
n int
want int
}{
{"small", 1, 1},
{"med", 100, 9},
{"large", 10000, 25},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := DivisorsSimple(tt.n); got != tt.want {
t.Errorf("DivisorsSimple() = %v, want %v", got, tt.want)
}
})
}
}
package main
// no concurrency used
func Divisors_simple(n int) int {
d := 1
for i := 1; i <= n/2; i++ {
if n%i == 0 {
d++
}
}
return d
}
package main
import (
"sync"
)
func check_channels(i int, n int, c chan int, wg *sync.WaitGroup) {
if n%i == 0 {
c <- 1 // <- is the "send" operator when a channel appears on the left.
}
wg.Done() // 4
}
func monitorWorker(wg *sync.WaitGroup, c chan int) {
wg.Wait() // 5
close(c)
}
func Divisors_channels(n int) int {
wg := &sync.WaitGroup{} // 1
c := make(chan int)
d := 1
for i := 1; i <= n/2; i++ {
wg.Add(1) // 2
go check_channels(i, n, c, wg) // 3
}
go monitorWorker(wg, c)
for o := range c {
d = d + o
}
return d
}
package main
import (
"sync"
)
func check_pointers(i int, n int, d *int, wg *sync.WaitGroup) {
if n%i == 0 {
*d = *d+1
}
wg.Done() // 4
}
func Divisors_pointers(n int) int {
d := 1
wg := &sync.WaitGroup{} // 1
for i := 1; i <= n/2; i++ {
wg.Add(1) // 2
go check_pointers(i, n, &d, wg) // 3
}
wg.Wait() // 5
return d
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment