Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

sieve of Eratosthenes example

  • Loading branch information...
commit 99f505df2e7b38f60c7208b3547397bd0bdfd0f1 1 parent 51105b8
@igrigorik authored
Showing with 219 additions and 0 deletions.
  1. +76 −0 spec/examples/go/sieve.go
  2. +143 −0 spec/examples/sieve_spec.rb
View
76 spec/examples/go/sieve.go
@@ -0,0 +1,76 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "strconv"
+)
+
+var nth = flag.Bool("n", false, "print the nth prime only")
+
+// Send the sequence 2, 3, 4, ... to returned channel
+func generate() chan int {
+ ch := make(chan int)
+ go func() {
+ for i := 2; ; i++ {
+ ch <- i
+ }
+ }()
+ return ch
+}
+
+// Filter out input values divisible by 'prime', send rest to returned channel
+func filter(in chan int, prime int) chan int {
+ out := make(chan int)
+ go func() {
+ for {
+ if i := <-in; i%prime != 0 {
+ out <- i
+ }
+ }
+ }()
+ return out
+}
+
+func sieve() chan int {
+ out := make(chan int)
+ go func() {
+ ch := generate()
+ for {
+ prime := <-ch
+ out <- prime
+ ch = filter(ch, prime)
+ }
+ }()
+ return out
+}
+
+func main() {
+ flag.Parse()
+ n, err := strconv.Atoi(flag.Arg(0))
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "bad argument\n")
+ os.Exit(1)
+ }
+ primes := sieve()
+ if *nth {
+ for i := 1; i < n; i++ {
+ <-primes
+ }
+ fmt.Println(<-primes)
+ } else {
+ for {
+ p := <-primes
+ if p <= n {
+ fmt.Println(p)
+ } else {
+ return
+ }
+ }
+ }
+}
View
143 spec/examples/sieve_spec.rb
@@ -0,0 +1,143 @@
+require "helper"
+
+describe "sieve of Eratosthenes" do
+
+ # http://golang.org/doc/go_tutorial.html#tmp_353
+
+ it "should work using Channel primitives" do
+
+ # send the sequence 2,3,4, ... to returned channel
+ def generate
+ ch = Go::Channel.new(name: 'generator', type: Integer)
+
+ go do
+ i = 1
+ loop { ch << i+= 1 }
+ end
+
+ return ch
+ end
+
+ # filter out input values divisible by *prime*, send rest to returned channel
+ def filter(in_channel, prime)
+ out = Go::Channel.new(name: "filter-#{prime}", type: Integer)
+
+ go do
+ loop do
+ i = in_channel.receive
+ out << i if (i % prime) != 0
+ end
+ end
+
+ return out
+ end
+
+ def sieve
+ out = Go::Channel.new(name: 'sieve', type: Integer)
+
+ go do
+ ch = generate
+ loop do
+ prime = ch.receive
+ out << prime
+ ch = filter(ch, prime)
+ end
+ end
+
+ return out
+ end
+
+ # run the sieve
+ n = 20
+ nth = false
+
+ primes = sieve
+ result = []
+
+ if nth
+ n.times { primes.receive }
+ puts primes.receive
+ else
+ loop do
+ p = primes.receive
+
+ if p <= n
+ result << p
+ else
+ break
+ end
+ end
+ end
+
+ result.should == [2,3,5,7,11,13,17,19]
+ end
+
+ it "should work with Ruby blocks" do
+
+ # send the sequence 2,3,4, ... to returned channel
+ generate = Proc.new do
+ ch = Go::Channel.new(name: 'generator-block', type: Integer)
+
+ go do
+ i = 1
+ loop { ch << i+= 1 }
+ end
+
+ ch
+ end
+
+ # filter out input values divisible by *prime*, send rest to returned channel
+ filtr = Proc.new do |in_channel, prime|
+ out = Go::Channel.new(name: "filter-#{prime}-block", type: Integer)
+
+ go do
+ loop do
+ i = in_channel.receive
+ out << i if (i % prime) != 0
+ end
+ end
+
+ out
+ end
+
+ sieve = -> do
+ out = Go::Channel.new(name: 'sieve-block', type: Integer)
+
+ go do
+ ch = generate.call
+
+ loop do
+ prime = ch.receive
+ out << prime
+ ch = filtr.call(ch, prime)
+ end
+ end
+
+ out
+ end
+
+ # run the sieve
+ n = 20
+ nth = false
+
+ primes = sieve.call
+ result = []
+
+ if nth
+ n.times { primes.receive }
+ puts primes.receive
+ else
+ loop do
+ p = primes.receive
+
+ if p <= n
+ result << p
+ else
+ break
+ end
+ end
+ end
+
+ result.should == [2,3,5,7,11,13,17,19]
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.