From f54ed4cd684217b4d9d50c94e1c09d427c90f141 Mon Sep 17 00:00:00 2001 From: Nicolas DUBIEN Date: Tue, 14 Apr 2020 19:37:58 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20Add=20an=20example=20based=20on?= =?UTF-8?q?=20Fibonacci=20(#576)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/001-simple/fibonacci/main.spec.ts | 87 +++++++++++++++++++ example/001-simple/fibonacci/src/fibonacci.ts | 10 +++ example/README.md | 1 + example/tsconfig.json | 2 +- 4 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 example/001-simple/fibonacci/main.spec.ts create mode 100644 example/001-simple/fibonacci/src/fibonacci.ts diff --git a/example/001-simple/fibonacci/main.spec.ts b/example/001-simple/fibonacci/main.spec.ts new file mode 100644 index 00000000000..004b93ec5b4 --- /dev/null +++ b/example/001-simple/fibonacci/main.spec.ts @@ -0,0 +1,87 @@ +import fc from 'fast-check'; +import { fibo } from './src/fibonacci'; + +// The complexity of the algorithm is O(n) +// As a consequence we limit the value of n to 1000 +const MaxN = 1000; + +describe('fibonacci', () => { + it('should be equal to the sum of fibo(n-1) and fibo(n-2)', () => { + fc.assert( + fc.property(fc.integer(2, MaxN), n => { + expect(fibo(n)).toBe(fibo(n - 1) + fibo(n - 2)); + }) + ); + }); + + // The following properties are listed on the Wikipedia page: + // https://fr.wikipedia.org/wiki/Suite_de_Fibonacci#Divisibilit%C3%A9_des_nombres_de_Fibonacci + + it('should fulfill fibo(p)*fibo(q+1)+fibo(p-1)*fibo(q) = fibo(p+q)', () => { + fc.assert( + fc.property(fc.integer(1, MaxN), fc.integer(0, MaxN), (p, q) => { + expect(fibo(p + q)).toBe(fibo(p) * fibo(q + 1) + fibo(p - 1) * fibo(q)); + }) + ); + }); + + it('should fulfill fibo(2p-1) = fibo²(p-1)+fibo²(p)', () => { + // Special case of the property above + fc.assert( + fc.property(fc.integer(1, MaxN), p => { + expect(fibo(2 * p - 1)).toBe(fibo(p - 1) * fibo(p - 1) + fibo(p) * fibo(p)); + }) + ); + }); + + it('should fulfill Catalan identity', () => { + fc.assert( + fc.property(fc.integer(0, MaxN), fc.integer(0, MaxN), (a, b) => { + const [p, q] = a < b ? [b, a] : [a, b]; + const sign = (p - q) % 2 === 0 ? 1n : -1n; // (-1)^(p-q) + expect(fibo(p) * fibo(p) - fibo(p - q) * fibo(p + q)).toBe(sign * fibo(q) * fibo(q)); + }) + ); + }); + + it('should fulfill Cassini identity', () => { + fc.assert( + fc.property(fc.integer(1, MaxN), fc.integer(0, MaxN), p => { + const sign = p % 2 === 0 ? 1n : -1n; // (-1)^p + expect(fibo(p + 1) * fibo(p - 1) - fibo(p) * fibo(p)).toBe(sign); + }) + ); + }); + + it('should fibo(nk) divisible by fibo(n)', () => { + fc.assert( + fc.property(fc.integer(1, MaxN), fc.integer(0, 100), (n, k) => { + expect(fibo(n * k) % fibo(n)).toBe(0n); + }) + ); + }); + + it('should fulfill gcd(fibo(a), fibo(b)) = fibo(gcd(a,b))', () => { + fc.assert( + fc.property(fc.integer(1, MaxN), fc.integer(1, MaxN), (a, b) => { + const gcd = (a: T, b: T, zero: T): T => { + a = a < zero ? (-a as T) : a; + b = b < zero ? (-b as T) : b; + if (b > a) { + const temp = a; + a = b; + b = temp; + } + // eslint-disable-next-line no-constant-condition + while (true) { + if (b == zero) return a; + a = (a % b) as T; + if (a == zero) return b; + b = (b % a) as T; + } + }; + expect(gcd(fibo(a), fibo(b), 0n)).toBe(fibo(gcd(a, b, 0))); + }) + ); + }); +}); diff --git a/example/001-simple/fibonacci/src/fibonacci.ts b/example/001-simple/fibonacci/src/fibonacci.ts new file mode 100644 index 00000000000..d5f9cbfdb0d --- /dev/null +++ b/example/001-simple/fibonacci/src/fibonacci.ts @@ -0,0 +1,10 @@ +export function fibo(n: number) { + let a = 0n; + let b = 1n; + for (let i = 0; i !== n; ++i) { + const previousA = a; + a = b; + b = previousA + b; + } + return a; +} diff --git a/example/README.md b/example/README.md index cbace9eded9..b501ff336ec 100644 --- a/example/README.md +++ b/example/README.md @@ -15,6 +15,7 @@ Following examples show how you could think about properties given algorithms ra 101 for property based: - `decompPrime` - Returns the list of prime factors corresponding to the input value +- `fibonacci` - Returns the item at a given position in the sequence of Fibonacci - `indexOf` - Returns the position of the first occurrence of `pattern` in `text` - `sort` - Returns a sorted copy of the input array diff --git a/example/tsconfig.json b/example/tsconfig.json index 24b964d9ae1..4d239487612 100644 --- a/example/tsconfig.json +++ b/example/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "downlevelIteration": true, - "target": "es5", + "target": "es2020", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true,