mirror of
https://hub.njuu.cf/TheAlgorithms/Python.git
synced 2023-10-11 13:06:12 +08:00
Iterative fibonacci with unittests from slash (#882)
* iterative and formula fibonacci methods Added two ways to calculate the fibonacci sequence: (1) iterative (2) formula. I've also added a timer decorator so someone can see the difference in computation time between these two methods. Added two unittests using the slash framework. * Update test_fibonacci.py * remove inline comments per Contributing Guidelines * Update sol5.py * Create placeholder.py * Update and rename maths/test_fibonacci.py to maths/tests/test_fibonacci.py * Delete placeholder.py * Create __init__.py * Update test_fibonacci.py * Rename Maths/lucasSeries.py to maths/lucasSeries.py * Update and rename Project Euler/Problem 01/sol5.py to project_euler/problem_01/sol6.py
This commit is contained in:
parent
6e894ba3e8
commit
9b945cb2b4
@ -1,8 +0,0 @@
|
||||
a=3
|
||||
result=0
|
||||
while a=<1000:
|
||||
if(a%3==0 and a%5==0):
|
||||
result+=a
|
||||
elif(a%15==0):
|
||||
result-=a
|
||||
print(result)
|
120
maths/fibonacci.py
Normal file
120
maths/fibonacci.py
Normal file
@ -0,0 +1,120 @@
|
||||
# fibonacci.py
|
||||
"""
|
||||
1. Calculates the iterative fibonacci sequence
|
||||
|
||||
2. Calculates the fibonacci sequence with a formula
|
||||
an = [ Phin - (phi)n ]/Sqrt[5]
|
||||
reference-->Su, Francis E., et al. "Fibonacci Number Formula." Math Fun Facts. <http://www.math.hmc.edu/funfacts>
|
||||
"""
|
||||
import math
|
||||
import functools
|
||||
import time
|
||||
from decimal import getcontext, Decimal
|
||||
|
||||
getcontext().prec = 100
|
||||
|
||||
|
||||
def timer_decorator(func):
|
||||
@functools.wraps(func)
|
||||
def timer_wrapper(*args, **kwargs):
|
||||
start = time.time()
|
||||
func(*args, **kwargs)
|
||||
end = time.time()
|
||||
if int(end - start) > 0:
|
||||
print(f'Run time for {func.__name__}: {(end - start):0.2f}s')
|
||||
else:
|
||||
print(f'Run time for {func.__name__}: {(end - start)*1000:0.2f}ms')
|
||||
return func(*args, **kwargs)
|
||||
return timer_wrapper
|
||||
|
||||
|
||||
# define Python user-defined exceptions
|
||||
class Error(Exception):
|
||||
"""Base class for other exceptions"""
|
||||
|
||||
|
||||
class ValueTooLargeError(Error):
|
||||
"""Raised when the input value is too large"""
|
||||
|
||||
|
||||
class ValueTooSmallError(Error):
|
||||
"""Raised when the input value is not greater than one"""
|
||||
|
||||
|
||||
class ValueLessThanZero(Error):
|
||||
"""Raised when the input value is less than zero"""
|
||||
|
||||
|
||||
def _check_number_input(n, min_thresh, max_thresh=None):
|
||||
"""
|
||||
:param n: single integer
|
||||
:type n: int
|
||||
:param min_thresh: min threshold, single integer
|
||||
:type min_thresh: int
|
||||
:param max_thresh: max threshold, single integer
|
||||
:type max_thresh: int
|
||||
:return: boolean
|
||||
"""
|
||||
try:
|
||||
if n >= min_thresh and max_thresh is None:
|
||||
return True
|
||||
elif min_thresh <= n <= max_thresh:
|
||||
return True
|
||||
elif n < 0:
|
||||
raise ValueLessThanZero
|
||||
elif n < min_thresh:
|
||||
raise ValueTooSmallError
|
||||
elif n > max_thresh:
|
||||
raise ValueTooLargeError
|
||||
except ValueLessThanZero:
|
||||
print("Incorrect Input: number must not be less than 0")
|
||||
except ValueTooSmallError:
|
||||
print(f'Incorrect Input: input number must be > {min_thresh} for the recursive calculation')
|
||||
except ValueTooLargeError:
|
||||
print(f'Incorrect Input: input number must be < {max_thresh} for the recursive calculation')
|
||||
return False
|
||||
|
||||
|
||||
@timer_decorator
|
||||
def fib_iterative(n):
|
||||
"""
|
||||
:param n: calculate Fibonacci to the nth integer
|
||||
:type n:int
|
||||
:return: Fibonacci sequence as a list
|
||||
"""
|
||||
n = int(n)
|
||||
if _check_number_input(n, 2):
|
||||
seq_out = [0, 1]
|
||||
a, b = 0, 1
|
||||
for _ in range(n-len(seq_out)):
|
||||
a, b = b, a+b
|
||||
seq_out.append(b)
|
||||
return seq_out
|
||||
|
||||
|
||||
@timer_decorator
|
||||
def fib_formula(n):
|
||||
"""
|
||||
:param n: calculate Fibonacci to the nth integer
|
||||
:type n:int
|
||||
:return: Fibonacci sequence as a list
|
||||
"""
|
||||
seq_out = [0, 1]
|
||||
n = int(n)
|
||||
if _check_number_input(n, 2, 1000000):
|
||||
sqrt = Decimal(math.sqrt(5))
|
||||
phi_1 = Decimal(1 + sqrt) / Decimal(2)
|
||||
phi_2 = Decimal(1 - sqrt) / Decimal(2)
|
||||
for i in range(2, n):
|
||||
temp_out = ((phi_1**Decimal(i)) - (phi_2**Decimal(i))) * (Decimal(sqrt) ** Decimal(-1))
|
||||
seq_out.append(int(temp_out))
|
||||
return seq_out
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
num = 20
|
||||
# print(f'{fib_recursive(num)}\n')
|
||||
# print(f'{fib_iterative(num)}\n')
|
||||
# print(f'{fib_formula(num)}\n')
|
||||
fib_iterative(num)
|
||||
fib_formula(num)
|
1
maths/tests/__init__.py
Normal file
1
maths/tests/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .. import fibonacci
|
34
maths/tests/test_fibonacci.py
Normal file
34
maths/tests/test_fibonacci.py
Normal file
@ -0,0 +1,34 @@
|
||||
"""
|
||||
To run with slash:
|
||||
1. run pip install slash (may need to install C++ builds from Visual Studio website)
|
||||
2. In the command prompt navigate to your project folder
|
||||
3. then type--> slash run -vv -k tags:fibonacci ..
|
||||
-vv indicates the level of verbosity (how much stuff you want the test to spit out after running)
|
||||
-k is a way to select the tests you want to run. This becomes much more important in large scale projects.
|
||||
"""
|
||||
|
||||
import slash
|
||||
from .. import fibonacci
|
||||
|
||||
default_fib = [0, 1, 1, 2, 3, 5, 8]
|
||||
|
||||
|
||||
@slash.tag('fibonacci')
|
||||
@slash.parametrize(('n', 'seq'), [(2, [0, 1]), (3, [0, 1, 1]), (9, [0, 1, 1, 2, 3, 5, 8, 13, 21])])
|
||||
def test_different_sequence_lengths(n, seq):
|
||||
"""Test output of varying fibonacci sequence lengths"""
|
||||
iterative = fibonacci.fib_iterative(n)
|
||||
formula = fibonacci.fib_formula(n)
|
||||
assert iterative == seq
|
||||
assert formula == seq
|
||||
|
||||
|
||||
@slash.tag('fibonacci')
|
||||
@slash.parametrize('n', [7.3, 7.8, 7.0])
|
||||
def test_float_input_iterative(n):
|
||||
"""Test when user enters a float value"""
|
||||
iterative = fibonacci.fib_iterative(n)
|
||||
formula = fibonacci.fib_formula(n)
|
||||
assert iterative == default_fib
|
||||
assert formula == default_fib
|
||||
|
9
project_euler/problem_01/sol6.py
Normal file
9
project_euler/problem_01/sol6.py
Normal file
@ -0,0 +1,9 @@
|
||||
a = 3
|
||||
result = 0
|
||||
while a < 1000:
|
||||
if(a % 3 == 0 or a % 5 == 0):
|
||||
result += a
|
||||
elif(a % 15 == 0):
|
||||
result -= a
|
||||
a += 1
|
||||
print(result)
|
Loading…
Reference in New Issue
Block a user