Skip to content

Instantly share code, notes, and snippets.

@miku
Last active April 22, 2016 11:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miku/854285f3a49c89822e39c2befff214c6 to your computer and use it in GitHub Desktop.
Save miku/854285f3a49c89822e39c2befff214c6 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"math/rand"
"strconv"
"strings"
"time"
"github.com/fatih/color"
)
type Reservoir struct {
Counter int
Sample [16]int
LastIndex int
}
func (r *Reservoir) String() string {
var vs []string
for i, v := range r.Sample {
if i == r.LastIndex {
green := color.New(color.Bold, color.FgGreen).SprintfFunc()
vs = append(vs, green(strconv.Itoa(v)))
} else {
vs = append(vs, strconv.Itoa(v))
}
}
return fmt.Sprintf("[%04d][%0.8f][%s]", r.Counter, r.P(), strings.Join(vs, ", "))
}
func (r *Reservoir) N() int {
return len(r.Sample)
}
func (r *Reservoir) P() float64 {
if r.Counter < r.N() {
return 0
}
return float64(r.N()) / float64(r.Counter)
}
func (r *Reservoir) Add(i int) {
if r.Counter < r.N() {
r.Sample[r.Counter] = i
r.LastIndex = r.Counter
}
if r.Counter > r.N() && rand.Float64() < r.P() {
ix := rand.Intn(r.N())
r.Sample[ix] = i
r.LastIndex = ix
}
r.Counter++
}
func stream(size int) <-chan int {
ch := make(chan int)
go func() {
for i := 0; i < size; i++ {
ch <- i
}
close(ch)
}()
return ch
}
func main() {
rand.Seed(int64(time.Now().Nanosecond()))
rr := &Reservoir{}
for i := range stream(1000) {
rr.Add(i)
fmt.Println(rr)
time.Sleep(10 * time.Millisecond)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment