Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented nth Fibonacci number using different methods #7

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
34 changes: 34 additions & 0 deletions .spec/math/fibonacci_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-- Define the test suite for the Fibonacci module
describe("Fibonacci", function()
-- Test the recursive Fibonacci function
it("works with fibonacci_recursive", function()
assert.is_equal(0, fibonacci.fibonacci_recursive(0))
assert.is_equal(1, fibonacci.fibonacci_recursive(1))
assert.is_equal(5, fibonacci.fibonacci_recursive(5))
assert.is_equal(55, fibonacci.fibonacci_recursive(10))
end)

-- Test the dynamic programming Fibonacci function
it("works with fibonacci_dp", function()
assert.is_equal(0, fibonacci.fibonacci_dp(0))
assert.is_equal(1, fibonacci.fibonacci_dp(1))
assert.is_equal(5, fibonacci.fibonacci_dp(5))
assert.is_equal(55, fibonacci.fibonacci_dp(10))
end)

-- Test Binet's formula Fibonacci function
it("works with fibonacci_binet", function()
assert.is_equal(0, fibonacci.fibonacci_binet(0))
assert.is_equal(1, fibonacci.fibonacci_binet(1))
assert.is_equal(5, fibonacci.fibonacci_binet(5))
assert.is_equal(55, fibonacci.fibonacci_binet(10))
end)

-- Test matrix exponentiation Fibonacci function
it("works with fibonacci_matrix", function()
assert.is_equal(0, fibonacci.fibonacci_matrix(0))
assert.is_equal(1, fibonacci.fibonacci_matrix(1))
assert.is_equal(5, fibonacci.fibonacci_matrix(5))
assert.is_equal(55, fibonacci.fibonacci_matrix(10))
end)
end)
6 changes: 6 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

80 changes: 80 additions & 0 deletions src/math/fibonacci.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
-- Fibonacci.lua
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Useless comment


-- Fibonacci Sequence:
-- The Fibonacci sequence is a series of numbers where each number (after the first two) is the sum of the two preceding ones.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment can stay

-- More information: https://en.wikipedia.org/wiki/Fibonacci_number

-- Author: Gyandeep
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not useful to readers of the code. Your name will be in the commit history if/when this is merged.


-- Implemented nth Fibonacci number using different approaches in O(2^N) , O(N) , O(logN) , O(1) .
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment is effectively redundant.



-- Function to calculate Fibonacci numbers using recursion
-- Time Complexity: O(2^n)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inaccurate. Exponential, but not 2^n (it grows with the golden ratio). I'd just use --! exponential time complexity, just for illustrative purposes here.

function fibonacci_recursive(n)
if n <= 0 then
return 0
elseif n == 1 then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer omitting the redundant else in if-return trees in Lua, so I would rewrite this as

-- or more concise: `if n <= 1 then return n end`
if n <= 0 then return 0 end
if n == 1 then return 1 end
return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)

return 1
else
return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2)
end
end

-- Function to calculate Fibonacci numbers using dynamic programming (DP)
-- Time Complexity: O(n)
function fibonacci_dp(n)
local fib = {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a fan of the unnecessary table here (wasteful in terms of memory). Remember that you just need the last two values, so two local variables suffice.

fib[0] = 0
fib[1] = 1
for i = 2, n do
fib[i] = fib[i - 1] + fib[i - 2]
end
return fib[n]
end

-- Function to calculate Fibonacci numbers using Binet's formula
-- Time Complexity: O(1)
-- Limitation: Accurate results up to n = 70 due to limitations of floating-point precision.
function fibonacci_binet(n)
local phi = (1 + math.sqrt(5)) / 2
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably write math.sqrt(5) as 5^0.5. That also has better properties for constant folding.

local psi = (1 - math.sqrt(5)) / 2
return math.floor((math.pow(phi, n) - math.pow(psi, n)) / math.sqrt(5))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't use math.pow, use ^ instead.

end

-- Function to multiply two 2x2 matrices
-- Time Complexity: O(1)
function matrix_multiply(a, b)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally this should not need to be here if I had finished and pushed my matrix "class" yet :P

Copy link
Collaborator

@appgurueu appgurueu Nov 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local c = {}
c[1] = a[1] * b[1] + a[2] * b[3]
c[2] = a[1] * b[2] + a[2] * b[4]
c[3] = a[3] * b[1] + a[4] * b[3]
c[4] = a[3] * b[2] + a[4] * b[4]
return c
end

-- Function to raise a 2x2 matrix to a power n using divide and conquer
-- Time Complexity: O(log(n))
function matrix_power(matrix, n)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is effectively exponentiation by squaring, which we already have and could use with a proper matrix class which provides multiplication. I'm not very keen on duplicating this.

if n == 0 then
return {1, 0, 0, 1} -- Identity matrix
elseif n % 2 == 0 then
local half_pow = matrix_power(matrix, n / 2)
return matrix_multiply(half_pow, half_pow)
else
local half_pow = matrix_power(matrix, (n - 1) / 2)
return matrix_multiply(matrix, matrix_multiply(half_pow, half_pow))
end
end

-- Function to calculate Fibonacci numbers using matrix exponentiation
-- Time Complexity: O(log(n))
function fibonacci_matrix(n)
if n <= 0 then
return 0
else
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else here is unneeded

local matrix = {1, 1, 1, 0}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This def. warrants a short comment, IMO. The crucial point here is that this matrix maps a vector (a, b) to (b, a + b).

local result_matrix = matrix_power(matrix, n - 1)
return result_matrix[1]
end
end
47 changes: 47 additions & 0 deletions src/math/sieve_eratosthenes.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
-- Sieve.lua

-- Sieve of Eratosthenes:
-- The Sieve of Eratosthenes is an efficient algorithm for finding all prime numbers up to a given limit.
-- More information: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes

-- Author: Gyandeep (https://www.linkedin.com/in/gyandeep-katiyar-790ba6256/)

-- Function to find all prime numbers up to a given limit using the Sieve of Eratosthenes
-- Time Complexity: O(n log log n)
function sieve_eratosthenes(limit)
-- Create a boolean array "is_prime" and initialize all entries as true
local is_prime = {}
for i = 2, limit do
is_prime[i] = true
end

-- Start with the first prime number, 2
local p = 2
while p * p <= limit do
-- If is_prime[p] is still true, then it is a prime number
if is_prime[p] == true then
-- Mark all multiples of p as non-prime
for i = p * p, limit, p do
is_prime[i] = false
end
end
p = p + 1
end

-- Collect the prime numbers into a table
local primes = {}
for i = 2, limit do
if is_prime[i] == true then
table.insert(primes, i)
end
end

return primes
end

-- Assert tests for the Sieve of Eratosthenes function
assert(#sieve_eratosthenes(10) == 4) -- There are 4 prime numbers up to 10 (2, 3, 5, 7)
assert(#sieve_eratosthenes(20) == 8) -- There are 8 prime numbers up to 20 (2, 3, 5, 7, 11, 13, 17, 19)
assert(#sieve_eratosthenes(50) == 15) -- There are 15 prime numbers up to 50

print("All tests passed!")
Loading