Bladeren bron

K5 product of consecutive fib numbers.

Frederic G. MARAND 4 jaren geleden
bovenliggende
commit
52098fa653

+ 11 - 0
go/.idea/runConfigurations/k5_product_of_consecutive_Fib_numbers.xml

@@ -0,0 +1,11 @@
+<component name="ProjectRunConfigurationManager">
+  <configuration default="false" name="k5 product of consecutive Fib numbers" type="GoTestRunConfiguration" factoryName="Go Test">
+    <module name="codewars" />
+    <working_directory value="$PROJECT_DIR$/" />
+    <go_parameters value="-i " />
+    <framework value="gotest" />
+    <kind value="PACKAGE" />
+    <package value="code.osinet.fr/fgm/codewars/kyu5/product_of_consecutive_fib_numbers" />
+    <method v="2" />
+  </configuration>
+</component>

+ 55 - 0
go/kyu5/product_of_consecutive_fib_numbers/k.go

@@ -0,0 +1,55 @@
+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]}
+}

+ 46 - 0
go/kyu5/product_of_consecutive_fib_numbers/k_test.go

@@ -0,0 +1,46 @@
+package kata_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+
+	. "code.osinet.fr/fgm/codewars/kyu5/product_of_consecutive_fib_numbers"
+)
+
+func dotest(prod uint64, exp [3]uint64) {
+	var ans = ProductFib(prod)
+	Expect(ans).To(Equal(exp))
+}
+
+var _ = Describe("Test Example", func() {
+
+	It("should handle basic cases", func() {
+		dotest(4895, [3]uint64{55, 89, 1})
+		dotest(5895, [3]uint64{89, 144, 0})
+		dotest(229970, [3]uint64{377, 610, 1})
+		dotest(74049690, [3]uint64{6765, 10946, 1})
+		dotest(84049690, [3]uint64{10946, 17711, 0})
+		dotest(193864606,  [3]uint64{10946, 17711, 1})
+		dotest(427859097160, [3]uint64{514229, 832040, 1})
+		dotest(5456077604922913920, [3]uint64{2971215073, 4807526976, 0})
+	})
+})
+
+func TestBinet(t *testing.T) {
+	OEIS_A000045 := [...]uint64{
+		0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597,
+		2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418,
+		317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465,
+		14930352, 24157817, 39088169, 63245986, 102334155,
+	}
+	var n int
+	var actual, expected uint64
+	for n, expected = range OEIS_A000045 {
+		actual = Binet(uint64(n))
+		if actual != expected {
+			t.Errorf("n: %d, expected: %d, got %d\n", n, expected, actual)
+		}
+	}
+}

+ 13 - 0
go/kyu5/product_of_consecutive_fib_numbers/product_of_consecutive_fib_numbers_suite_test.go

@@ -0,0 +1,13 @@
+package kata_test
+
+import (
+	"testing"
+
+	. "github.com/onsi/ginkgo"
+	. "github.com/onsi/gomega"
+)
+
+func TestProductOfConsecutiveFibNumbers(t *testing.T) {
+	RegisterFailHandler(Fail)
+	RunSpecs(t, "ProductOfConsecutiveFibNumbers Suite")
+}