Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions kata/3-kyu/index.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
- [Battleship field validator](battleship-field-validator "52bb6539a4cf1b12d90005b7")
- [Make a spiral](make-a-spiral "534e01fbbb17187c7e0000c6")
- [Path Finder #3: the Alpinist](path-finder-number-3-the-alpinist "576986639772456f6f00030c")
- [The Millionth Fibonacci Kata](the-millionth-fibonacci-kata "53d40c1e2f13e331fc000c26")
37 changes: 37 additions & 0 deletions kata/3-kyu/the-millionth-fibonacci-kata/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# [The Millionth Fibonacci Kata](https://www.codewars.com/kata/the-millionth-fibonacci-kata "https://www.codewars.com/kata/53d40c1e2f13e331fc000c26")

The year is 1214. One night, Pope Innocent III awakens to find the archangel Gabriel floating before him. Gabriel thunders to the pope:

> Gather all the learned men in Pisa, especially Leonardo Fibonacci. In order for the crusades in the holy lands to be successful, these
> men must calculate the *millionth* number in Fibonacci's recurrence. Fail to do this, and your armies will never reclaim the holy land. It
> is His will.

The angel then vanishes in an explosion of white light.

Pope Innocent III sits in his bed in awe. *How much is a million?* he thinks to himself. He was never very good at math.

He tries writing the number down, but because everyone in Europe is still using Roman numerals at this moment in history, he cannot
represent this number. If he only knew about the invention of zero, it might make this sort of thing easier.

He decides to go back to bed. He consoles himself, *The Lord would never challenge me thus; this must have been some deceit by the devil. A
pretty horrendous nightmare, to be sure.*

Pope Innocent III's armies would go on to conquer Constantinople (now Istanbul), but they would never reclaim the holy land as he desired.

---------------------------

In this kata you will have to calculate `fib(n)` where:

fib(0) := 0
fib(1) := 1
fib(n + 2) := fib(n + 1) + fib(n)

Write an algorithm that can handle `n` up to `2000000`.

Your algorithm must output the exact integer answer, to full precision. Also, it must correctly handle negative numbers as input.

**HINT I**: Can you rearrange the equation `fib(n + 2) = fib(n + 1) + fib(n)` to find `fib(n)` if you already know `fib(n + 1)` and
`fib(n + 2)`? Use this to reason what value `fib` has to have for negative values.

**HINT II**:
See https://web.archive.org/web/20220614001843/https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-11.html#%_sec_1.2.4
16 changes: 16 additions & 0 deletions kata/3-kyu/the-millionth-fibonacci-kata/main/Fibonacci.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import static java.math.BigInteger.*;

import java.math.BigInteger;

interface Fibonacci {
static BigInteger fib(BigInteger n) {
BigInteger result = fib(ONE, ZERO, ZERO, ONE, n.abs());
return n.signum() < 0 && !n.testBit(0) ? result.negate() : result;
}

private static BigInteger fib(BigInteger a, BigInteger b, BigInteger p, BigInteger q, BigInteger n) {
return n.equals(ZERO) ? b :
!n.testBit(0) ? fib(a, b, p.pow(2).add(q.pow(2)), p.multiply(q.multiply(TWO)).add(q.pow(2)), n.divide(TWO)) :
fib(b.multiply(q).add(a.multiply(q)).add(a.multiply(p)), b.multiply(p).add(a.multiply(q)), p, q, n.subtract(ONE));
}
}
22 changes: 22 additions & 0 deletions kata/3-kyu/the-millionth-fibonacci-kata/test/FibonacciTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.math.BigInteger;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

class FibonacciTest {
@ParameterizedTest
@CsvSource(textBlock = """
0, 0
1, 1
2, 1
3, 2
4, 3
5, 5
-1, 1
-6, -8
""")
void sample(BigInteger input, BigInteger expected) {
assertEquals(expected, Fibonacci.fib(input));
}
}