12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
- package kata
- import (
- "math"
- )
- var sqrt5 = math.Sqrt(5)
- var Phi1 = (1.0 + sqrt5) / 2
- var Phi2 = (1.0 - sqrt5) / 2
- /*
- Binet returns the n-th element of the Fibonacci suite using Binet's formula.
- */
- func Binet(n uint64) uint64 {
- fn := float64(n)
- fl := (math.Pow(Phi1, fn) - math.Pow(Phi2, fn)) / sqrt5
- res := uint64(math.Round(fl))
- return res
- }
- /*
- Prod return Fibonacci(n)*Fibonacci(n+1).
- */
- func Prod(n uint64) uint64 {
- return Binet(n) * Binet(n+1)
- }
- /*
- Near returns an integer n such as Fib(n)*Fib(n+1) be close to be the argument received.
- The approximation used is based on Binet's formula for Fibonacci.
- */
- func Near(prod uint64) (n uint64, ok bool) {
- // fn is within 1 of the actual value if it exists.
- fn := math.Log(math.Sqrt(5*float64(prod)/Phi1)) / math.Log(Phi1)
- b, c := uint64(math.Floor(fn)), uint64(math.Ceil(fn))
- a, d := b-1, c+1
- for _, x := range [...]uint64{a, b, c, d} {
- if Prod(x) == prod {
- return x, true
- }
- }
- for _, x := range [...]uint64{a, b, c, d} {
- if Prod(x) > prod {
- return x, false
- }
- }
- return d+1, false
- }
- func ProductFib(prod uint64) [3]uint64 {
- // n is within 1 of the actual potential solution.
- n, ok := Near(prod)
- return [3]uint64{Binet(n), Binet(n + 1), map[bool]uint64{false: 0, true: 1}[ok]}
- }
|