How to resolve the algorithm Sieve of Eratosthenes step by step in the Go programming language
How to resolve the algorithm Sieve of Eratosthenes step by step in the Go programming language
Table of Contents
Problem Statement
The Sieve of Eratosthenes is a simple algorithm that finds the prime numbers up to a given integer.
Implement the Sieve of Eratosthenes algorithm, with the only allowed optimization that the outer loop can stop at the square root of the limit, and the inner loop may start at the square of the prime just found. That means especially that you shouldn't optimize by using pre-computed wheels, i.e. don't assume you need only to cross out odd numbers (wheel based on 2), numbers equal to 1 or 5 modulo 6 (wheel based on 2 and 3), or similar wheels based on low primes. If there's an easy way to add such a wheel based optimization, implement it as an alternative version.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm Sieve of Eratosthenes step by step in the Go programming language
Source code 1:
This is a basic implementation of the sieve of Eratosthenes to find prime numbers up to a limit of 201.
- The program creates a boolean array
c
of sizelimit
with all values initialized tofalse
. - It iterates over numbers from 2 to the square root of
limit
, marking their multiples as composite in thec
array. - After the sieve is complete, it iterates over the
c
array and prints the prime numbers.
Source code 2:
This is a more efficient implementation of the sieve of Eratosthenes that uses bit operations to store the prime numbers.
- The program creates a slice
cmpsts
ofuint
values to represent the composite numbers. - It iterates over the odd numbers up to the square root of the top limit, marking their multiples as composite in the
cmpsts
slice using bitwise operations. - The
primesOdds
function returns a closure that generates the next prime number. - The main function prints the prime numbers up to 100 and counts the number of prime numbers up to 1 million.
Source code 3:
This is a recursive implementation of the sieve of Eratosthenes using goroutines.
- The
primes
function generates a channel of prime numbers. - The
Generate
function generates a channel of increasing numbers. - The
Filter
function filters out the multiples of a given prime number from a channel of numbers. - The
Sieve
function daisy-chainsFilter
processes to create a channel of prime numbers. - The main function prints the first 100,000 prime numbers.
Source code 4:
This is another implementation of the sieve of Eratosthenes using goroutines and a different filter algorithm.
- The
Generate
function generates a channel of increasing numbers. - The
Filter
function filters out the multiples of a given prime number from a channel of numbers by counting. - The
Sieve
function postpones the creation ofFilter
processes until they are needed, making the recursion shallower. - The main function prints the first 25,000 prime numbers, but it could be modified to print a different number of prime numbers.
Source code 5:
This is a simple implementation of the sieve of Eratosthenes that uses channels to communicate between goroutines.
- The
PrimeSieve
function generates a channel of prime numbers. - The main function prints the first 100 prime numbers from the channel.
- The
PrimeSieve
function generates prime numbers by repeatedly removing the multiples of the current prime number from a channel of increasing numbers.
Source code in the go programming language
package main
import "fmt"
func main() {
const limit = 201 // means sieve numbers < 201
// sieve
c := make([]bool, limit) // c for composite. false means prime candidate
c[1] = true // 1 not considered prime
p := 2
for {
// first allowed optimization: outer loop only goes to sqrt(limit)
p2 := p * p
if p2 >= limit {
break
}
// second allowed optimization: inner loop starts at sqr(p)
for i := p2; i < limit; i += p {
c[i] = true // it's a composite
}
// scan to get next prime for outer loop
for {
p++
if !c[p] {
break
}
}
}
// sieve complete. now print a representation.
for n := 1; n < limit; n++ {
if c[n] {
fmt.Print(" .")
} else {
fmt.Printf("%3d", n)
}
if n%20 == 0 {
fmt.Println("")
}
}
}
package main
import (
"fmt"
"math"
)
func primesOdds(top uint) func() uint {
topndx := int((top - 3) / 2)
topsqrtndx := (int(math.Sqrt(float64(top))) - 3) / 2
cmpsts := make([]uint, (topndx/32)+1)
for i := 0; i <= topsqrtndx; i++ {
if cmpsts[i>>5]&(uint(1)<<(uint(i)&0x1F)) == 0 {
p := (i << 1) + 3
for j := (p*p - 3) >> 1; j <= topndx; j += p {
cmpsts[j>>5] |= 1 << (uint(j) & 0x1F)
}
}
}
i := -1
return func() uint {
oi := i
if i <= topndx {
i++
}
for i <= topndx && cmpsts[i>>5]&(1<<(uint(i)&0x1F)) != 0 {
i++
}
if oi < 0 {
return 2
} else {
return (uint(oi) << 1) + 3
}
}
}
func main() {
iter := primesOdds(100)
for v := iter(); v <= 100; v = iter() {
print(v, " ")
}
iter = primesOdds(1000000)
count := 0
for v := iter(); v <= 1000000; v = iter() {
count++
}
fmt.Printf("\r\n%v\r\n", count)
}
package main
import "fmt"
type xint uint64
type xgen func()(xint)
func primes() func()(xint) {
pp, psq := make([]xint, 0), xint(25)
var sieve func(xint, xint)xgen
sieve = func(p, n xint) xgen {
m, next := xint(0), xgen(nil)
return func()(r xint) {
if next == nil {
r = n
if r <= psq {
n += p
return
}
next = sieve(pp[0] * 2, psq) // chain in
pp = pp[1:]
psq = pp[0] * pp[0]
m = next()
}
switch {
case n < m: r, n = n, n + p
case n > m: r, m = m, next()
default: r, n, m = n, n + p, next()
}
return
}
}
f := sieve(6, 9)
n, p := f(), xint(0)
return func()(xint) {
switch {
case p < 2: p = 2
case p < 3: p = 3
default:
for p += 2; p == n; {
p += 2
if p > n {
n = f()
}
}
pp = append(pp, p)
}
return p
}
}
func main() {
for i, p := 0, primes(); i < 100000; i++ {
fmt.Println(p())
}
}
package main
import "fmt"
// Send the sequence 2, 3, 4, ... to channel 'out'
func Generate(out chan<- int) {
for i := 2; ; i++ {
out <- i // Send 'i' to channel 'out'
}
}
// Copy the values from 'in' channel to 'out' channel,
// removing the multiples of 'prime' by counting.
// 'in' is assumed to send increasing numbers
func Filter(in <-chan int, out chan<- int, prime int) {
m := prime + prime // first multiple of prime
for {
i := <- in // Receive value from 'in'
for i > m {
m = m + prime // next multiple of prime
}
if i < m {
out <- i // Send 'i' to 'out'
}
}
}
// The prime sieve: Daisy-chain Filter processes
func Sieve(out chan<- int) {
gen := make(chan int) // Create a new channel
go Generate(gen) // Launch Generate goroutine
for {
prime := <- gen
out <- prime
ft := make(chan int)
go Filter(gen, ft, prime)
gen = ft
}
}
func main() {
sv := make(chan int) // Create a new channel
go Sieve(sv) // Launch Sieve goroutine
for i := 0; i < 1000; i++ {
prime := <- sv
if i >= 990 {
fmt.Printf("%4d ", prime)
if (i+1)%20==0 {
fmt.Println("")
}
}
}
}
package main
import "fmt"
// Send the sequence 2, 3, 4, ... to channel 'out'
func Generate(out chan<- int) {
for i := 2; ; i++ {
out <- i // Send 'i' to channel 'out'
}
}
// Copy the values from 'in' channel to 'out' channel,
// removing the multiples of 'prime' by counting.
// 'in' is assumed to send increasing numbers
func Filter(in <-chan int, out chan<- int, prime int) {
m := prime * prime // start from square of prime
for {
i := <- in // Receive value from 'in'
for i > m {
m = m + prime // next multiple of prime
}
if i < m {
out <- i // Send 'i' to 'out'
}
}
}
// The prime sieve: Postponed-creation Daisy-chain of Filters
func Sieve(out chan<- int) {
gen := make(chan int) // Create a new channel
go Generate(gen) // Launch Generate goroutine
p := <- gen
out <- p
p = <- gen // make recursion shallower ---->
out <- p // (Go channels are _push_, not _pull_)
base_primes := make(chan int) // separate primes supply
go Sieve(base_primes)
bp := <- base_primes // 2 <---- here
bq := bp * bp // 4
for {
p = <- gen
if p == bq { // square of a base prime
ft := make(chan int)
go Filter(gen, ft, bp) // filter multiples of bp in gen out
gen = ft
bp = <- base_primes // 3
bq = bp * bp // 9
} else {
out <- p
}
}
}
func main() {
sv := make(chan int) // Create a new channel
go Sieve(sv) // Launch Sieve goroutine
lim := 25000
for i := 0; i < lim; i++ {
prime := <- sv
if i >= (lim-10) {
fmt.Printf("%4d ", prime)
if (i+1)%20==0 {
fmt.Println("")
}
}
}
}
package main
import "fmt"
func main() {
primes := make(chan int)
go PrimeSieve(primes)
p := <-primes
for p < 100 {
fmt.Printf("%d ", p)
p = <-primes
}
fmt.Println()
}
func PrimeSieve(out chan int) {
out <- 2
out <- 3
primes := make(chan int)
go PrimeSieve(primes)
var p int
<-primes
p = <-primes
sieve := make(map[int]int)
q := p * p
n := p
for {
n += 2
step, isComposite := sieve[n]
if isComposite {
delete(sieve, n)
m := n + step
for sieve[m] != 0 {
m += step
}
sieve[m] = step
} else if n < q {
out <- n
} else {
step = p + p
m := n + step
for sieve[m] != 0 {
m += step
}
sieve[m] = step
p = <-primes
q = p * p
}
}
}
You may also check:How to resolve the algorithm Window creation step by step in the Delphi programming language
You may also check:How to resolve the algorithm SHA-256 Merkle tree step by step in the Perl programming language
You may also check:How to resolve the algorithm Canonicalize CIDR step by step in the Haskell programming language
You may also check:How to resolve the algorithm Find common directory path step by step in the Swift programming language
You may also check:How to resolve the algorithm Permutations step by step in the JavaScript programming language