package main
import "fmt"

// Send the sequence 2, 3, 4, ... to channel 'ch'
func Generate(ch chan<- int) {
	for i := 2; ; i++ {
		ch <- i    // Send 'i' to channel 'ch'
	}
}

// Copy the values from channel 'in' to channel 'out',
// removing the multiples of 'prime'.
// 'in' assumed to send increasing numbers
func Filter(in <-chan int, out chan<- int, prime int) {
	m := prime + prime
	for {
		i := <- in    // Receive value from 'in'
		for i > m {
			m = m + prime
		}
		if i < m {
			out <- i  // Send 'i' to 'out'
		}
	}
}

// The prime sieve: Daisy-chain Filter processes
func Sieve(out chan<- int) {
	ch := make(chan int)     // Create a new channel
	go Generate(ch)          // Launch Generate goroutine
	for  {
		prime := <-ch
		out <- prime
		ch1 := make(chan int)
		go Filter(ch, ch1, prime)
		ch = ch1
	}
}

func main() {
	ch := make(chan int)     // Create a new channel
	go Sieve(ch)             // Launch Sieve goroutine
	m := 3000
	for i := 0; i < m; i++ {
		prime := <-ch
		if i >= (m-5) {
		    fmt.Printf("%4d ", prime)
		    //if (i+1)%10==0 {
			//	fmt.Println("")
		    //}
		}
	}
}
/*
3000:	time: 4.02 memory: 789504 signal:0   ---- n^2.1 ----
27409 27427 27431 27437 27449 

2000:	time: 1.75 memory: 789504 signal:0   ---- n^2.1 ----
17359 17377 17383 17387 17389 

1000:	time: 0.39 memory: 789504 signal:0     
7879 7883 7901 7907 7919 
*/