From a49dc188e003205e685c1872cc133acc05c598ec Mon Sep 17 00:00:00 2001 From: Gabriel Augendre Date: Sat, 14 Aug 2021 07:54:13 +0200 Subject: [PATCH] Implement primes counter in go --- .gitignore | 2 ++ README.md | 6 ++++ go.mod | 3 ++ main.go | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 go.mod create mode 100644 main.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1099ec2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea +go-primes-counter diff --git a/README.md b/README.md new file mode 100644 index 0000000..128d8b9 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Primes counter +````shell +go build +./go-primes-counter -h +./go-primes-counter -start 10 -max 1000 -print-count -1 -step-size 100 +```` \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a48c0dd --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module go-primes-counter + +go 1.16 diff --git a/main.go b/main.go new file mode 100644 index 0000000..1a1c2cf --- /dev/null +++ b/main.go @@ -0,0 +1,91 @@ +package main + +import ( + "flag" + "fmt" + "sync" +) + +func main() { + start, max, step, printCount := parseArgs() + if max < start { + start, max = max, start + } + totalLength := max - start + if totalLength < step { + step = totalLength + } + + // Start jobs + var wg sync.WaitGroup + results := make(chan int, 100) + for i := start; i < max; i += step { + wg.Add(1) + go worker(i, i+step, &wg, results) + } + + // Collect results + go waitForWorkers(&wg, results) + var primes []int + for prime := range results { + primes = append(primes, prime) + } + + // Print results + fmt.Println("There are", len(primes), "primes between", start, "and", max) + if printCount > len(primes) { + printCount = -1 + } + if printCount < 0 { + fmt.Println("Here they are:") + fmt.Println(primes) + } else { + fmt.Println("Here's a free sample:") + fmt.Println(primes[:printCount]) + } +} + +func worker(start, end int, wg *sync.WaitGroup, results chan<- int) { + defer wg.Done() + for i := start; i < end; i++ { + if IsPrime(i) { + results <- i + } + } +} + +func waitForWorkers(wg *sync.WaitGroup, results chan int) { + wg.Wait() + close(results) +} + +// IsPrime determines if the given int is a prime number or not. +// The method currently implemented by this method is not smart and not +// optimized for large numbers. +func IsPrime(n int) bool { + if n <= 3 { + return n > 1 + } + if n%2 == 0 || n%3 == 0 { + return false + } + i := 5 + for i*i <= n { + if n%i == 0 || n%(i+2) == 0 { + return false + } + i += 6 + } + return true +} + +func parseArgs() (int, int, int, int) { + start := flag.Int("start", 0, "The start number") + max := flag.Int("max", 10_000, "The end value") + step := flag.Int("step-size", 1_000, "The job size") + printCountDesc := `Number of primes to print. -1 to print all. +Primes are not guaranteed to be sorted.` + printCount := flag.Int("print-count", 20, printCountDesc) + flag.Parse() + return *start, *max, *step, *printCount +}