Skip to content

Commit f5c9741

Browse files
* docs: kata description * feat: kata/the-millionth-fibonacci-kata * test: cover negative fib numbers * test: cover negative fib numbers F(-1) = 0 - (-1) = 1 --------- Co-authored-by: ParanoidUser <[email protected]>
1 parent 9f6d641 commit f5c9741

File tree

4 files changed

+76
-0
lines changed

4 files changed

+76
-0
lines changed

kata/3-kyu/index.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
- [Battleship field validator](battleship-field-validator "52bb6539a4cf1b12d90005b7")
22
- [Make a spiral](make-a-spiral "534e01fbbb17187c7e0000c6")
33
- [Path Finder #3: the Alpinist](path-finder-number-3-the-alpinist "576986639772456f6f00030c")
4+
- [The Millionth Fibonacci Kata](the-millionth-fibonacci-kata "53d40c1e2f13e331fc000c26")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# [The Millionth Fibonacci Kata](https://www.codewars.com/kata/the-millionth-fibonacci-kata "https://www.codewars.com/kata/53d40c1e2f13e331fc000c26")
2+
3+
The year is 1214. One night, Pope Innocent III awakens to find the archangel Gabriel floating before him. Gabriel thunders to the pope:
4+
5+
> Gather all the learned men in Pisa, especially Leonardo Fibonacci. In order for the crusades in the holy lands to be successful, these
6+
> men must calculate the *millionth* number in Fibonacci's recurrence. Fail to do this, and your armies will never reclaim the holy land. It
7+
> is His will.
8+
9+
The angel then vanishes in an explosion of white light.
10+
11+
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.
12+
13+
He tries writing the number down, but because everyone in Europe is still using Roman numerals at this moment in history, he cannot
14+
represent this number. If he only knew about the invention of zero, it might make this sort of thing easier.
15+
16+
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
17+
pretty horrendous nightmare, to be sure.*
18+
19+
Pope Innocent III's armies would go on to conquer Constantinople (now Istanbul), but they would never reclaim the holy land as he desired.
20+
21+
---------------------------
22+
23+
In this kata you will have to calculate `fib(n)` where:
24+
25+
fib(0) := 0
26+
fib(1) := 1
27+
fib(n + 2) := fib(n + 1) + fib(n)
28+
29+
Write an algorithm that can handle `n` up to `2000000`.
30+
31+
Your algorithm must output the exact integer answer, to full precision. Also, it must correctly handle negative numbers as input.
32+
33+
**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
34+
`fib(n + 2)`? Use this to reason what value `fib` has to have for negative values.
35+
36+
**HINT II**:
37+
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
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import static java.math.BigInteger.*;
2+
3+
import java.math.BigInteger;
4+
5+
interface Fibonacci {
6+
static BigInteger fib(BigInteger n) {
7+
BigInteger result = fib(ONE, ZERO, ZERO, ONE, n.abs());
8+
return n.signum() < 0 && !n.testBit(0) ? result.negate() : result;
9+
}
10+
11+
private static BigInteger fib(BigInteger a, BigInteger b, BigInteger p, BigInteger q, BigInteger n) {
12+
return n.equals(ZERO) ? b :
13+
!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)) :
14+
fib(b.multiply(q).add(a.multiply(q)).add(a.multiply(p)), b.multiply(p).add(a.multiply(q)), p, q, n.subtract(ONE));
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import static org.junit.jupiter.api.Assertions.assertEquals;
2+
3+
import java.math.BigInteger;
4+
import org.junit.jupiter.params.ParameterizedTest;
5+
import org.junit.jupiter.params.provider.CsvSource;
6+
7+
class FibonacciTest {
8+
@ParameterizedTest
9+
@CsvSource(textBlock = """
10+
0, 0
11+
1, 1
12+
2, 1
13+
3, 2
14+
4, 3
15+
5, 5
16+
-1, 1
17+
-6, -8
18+
""")
19+
void sample(BigInteger input, BigInteger expected) {
20+
assertEquals(expected, Fibonacci.fib(input));
21+
}
22+
}

0 commit comments

Comments
 (0)