go-primes-counter/main.go

91 lines
1.8 KiB
Go

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
}