Created
November 1, 2020 14:29
-
-
Save TarasJan/283818d40922df9ae350cf4bb858b81c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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