Skip to content

Instantly share code, notes, and snippets.

@TarasJan
Created November 1, 2020 14:29
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 TarasJan/283818d40922df9ae350cf4bb858b81c to your computer and use it in GitHub Desktop.
Save TarasJan/283818d40922df9ae350cf4bb858b81c to your computer and use it in GitHub Desktop.
package main
import (
"encoding/json"
"io/ioutil"
"log"
"math"
"sync"
"time"
)
type Measurement struct {
X int `json:"x"`
Result int `json:"result"`
Timing time.Duration `json:"timing"`
Name string `json:"name"`
}
func (m *Measurement) SetTiming(d time.Duration) {
m.Timing = d
}
func (m *Measurement) SetResult(y int) {
m.Result = y
}
func elapsed() func(*Measurement) {
start := time.Now()
return func(m *Measurement) {
epsilon := time.Since(start)
m.SetTiming(epsilon)
}
}
func measureForMethod(x int, f func(int) int, name string) *Measurement {
m := &Measurement{x, x, time.Duration(0), name}
func(measure *Measurement) {
defer elapsed()(m)
m.SetResult(f(x))
}(m)
return m
}
// Classic recursive solution
func fibo(x int) int {
switch {
case x < 0:
log.Fatal("Fibonacci can be called only for positive integers")
return 0
case x == 0:
return 0
case x == 1:
return 1
default:
return fibo(x-1) + fibo(x-2)
}
}
// Linear solution
func fibo2(x int) int {
a := 0
b := 1
switch {
case x < 0:
log.Fatal("Fibonacci can be called only for positive integers")
return 0
case x == 0:
return a
case x == 1:
return b
default:
for i := 2; i < x+1; i++ {
b = a + b
a = b - a
}
return b
}
}
// Mathematical approach
func fibo3(x int) int {
if x < 0 {
log.Fatal("Fibonacci can be called only for positive integers")
}
sqrt := math.Sqrt(5)
p := (1 + sqrt) / 2.0
return int(math.RoundToEven((math.Pow(p, float64(x))) / sqrt))
}
func main() {
limit := 45
methodNo := 1
answerChannel := make(chan *Measurement, 300)
var wg sync.WaitGroup
for i := 0; i < limit; i++ {
val := i
wg.Add(methodNo)
go func() {
defer wg.Done()
answerChannel <- measureForMethod(val, fibo, "recurrence")
}()
go func() {
defer wg.Done()
answerChannel <- measureForMethod(val, fibo2, "linear")
}()
go func() {
defer wg.Done()
answerChannel <- measureForMethod(val, fibo3, "numeric")
}()
}
wg.Wait()
measures := []*Measurement{}
for j := 0; j < methodNo*limit; j++ {
measure := <-answerChannel
measures = append(measures, measure)
}
results := map[string][]*Measurement{"results": measures}
parsedMeasures, _ := json.Marshal(results)
log.Printf(string(parsedMeasures))
err := ioutil.WriteFile("fibo-results.json", parsedMeasures, 0644)
if err != nil {
log.Panic(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment