From 1318e462be348953ffe453e908b9557130323ba7 Mon Sep 17 00:00:00 2001 From: StephenGemin <45926479+StephenGemin@users.noreply.github.com> Date: Thu, 6 Jun 2019 20:46:23 -0400 Subject: [PATCH 01/11] 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. --- maths/fibonacci.py | 120 ++++++++++++++++++++++++++++++++++++++++ maths/test_fibonacci.py | 25 +++++++++ 2 files changed, 145 insertions(+) create mode 100644 maths/fibonacci.py create mode 100644 maths/test_fibonacci.py diff --git a/maths/fibonacci.py b/maths/fibonacci.py new file mode 100644 index 000000000000..28554f8aa378 --- /dev/null +++ b/maths/fibonacci.py @@ -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. +""" +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) # to ensure number is an integer, even if input is float + 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) # to ensure number is an integer, even if input is float + 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) diff --git a/maths/test_fibonacci.py b/maths/test_fibonacci.py new file mode 100644 index 000000000000..dcd6faf33120 --- /dev/null +++ b/maths/test_fibonacci.py @@ -0,0 +1,25 @@ +import slash +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 + From 04533a92914f801b33b59e12e5160f9b3f0e7cc0 Mon Sep 17 00:00:00 2001 From: StephenGemin <45926479+StephenGemin@users.noreply.github.com> Date: Thu, 6 Jun 2019 20:53:31 -0400 Subject: [PATCH 02/11] Update test_fibonacci.py --- maths/test_fibonacci.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/maths/test_fibonacci.py b/maths/test_fibonacci.py index dcd6faf33120..8da9d93b6a61 100644 --- a/maths/test_fibonacci.py +++ b/maths/test_fibonacci.py @@ -1,3 +1,12 @@ +""" +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 import fibonacci From a4aba45cb682db580e059d53c98d1f089be87e67 Mon Sep 17 00:00:00 2001 From: StephenGemin <45926479+StephenGemin@users.noreply.github.com> Date: Thu, 6 Jun 2019 20:54:34 -0400 Subject: [PATCH 03/11] remove inline comments per Contributing Guidelines --- maths/fibonacci.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/fibonacci.py b/maths/fibonacci.py index 28554f8aa378..0a0611f21379 100644 --- a/maths/fibonacci.py +++ b/maths/fibonacci.py @@ -82,7 +82,7 @@ def fib_iterative(n): :type n:int :return: Fibonacci sequence as a list """ - n = int(n) # to ensure number is an integer, even if input is float + n = int(n) if _check_number_input(n, 2): seq_out = [0, 1] a, b = 0, 1 @@ -100,7 +100,7 @@ def fib_formula(n): :return: Fibonacci sequence as a list """ seq_out = [0, 1] - n = int(n) # to ensure number is an integer, even if input is float + n = int(n) if _check_number_input(n, 2, 1000000): sqrt = Decimal(math.sqrt(5)) phi_1 = Decimal(1 + sqrt) / Decimal(2) From fdc2ab9f18e513611c7b1093c2be66d9bf8384ec Mon Sep 17 00:00:00 2001 From: StephenGemin <45926479+StephenGemin@users.noreply.github.com> Date: Fri, 7 Jun 2019 11:26:35 -0400 Subject: [PATCH 04/11] Update sol5.py --- Project Euler/Problem 01/sol5.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Project Euler/Problem 01/sol5.py b/Project Euler/Problem 01/sol5.py index 2cb67d2524e2..0946bfaf18e7 100644 --- a/Project Euler/Problem 01/sol5.py +++ b/Project Euler/Problem 01/sol5.py @@ -1,8 +1,8 @@ -a=3 -result=0 -while a=<1000: - if(a%3==0 and a%5==0): - result+=a - elif(a%15==0): - result-=a +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) From 9f8a8d07da988217a86c15b7023c140094b83648 Mon Sep 17 00:00:00 2001 From: StephenGemin <45926479+StephenGemin@users.noreply.github.com> Date: Fri, 7 Jun 2019 11:41:50 -0400 Subject: [PATCH 05/11] Create placeholder.py --- maths/tests/placeholder.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 maths/tests/placeholder.py diff --git a/maths/tests/placeholder.py b/maths/tests/placeholder.py new file mode 100644 index 000000000000..d4f031666c4c --- /dev/null +++ b/maths/tests/placeholder.py @@ -0,0 +1 @@ +# Just creating this so the folder isn't empty From 409e793fb995c00f6cdc296e426d7c77e336b764 Mon Sep 17 00:00:00 2001 From: StephenGemin <45926479+StephenGemin@users.noreply.github.com> Date: Fri, 7 Jun 2019 11:43:15 -0400 Subject: [PATCH 06/11] Update and rename maths/test_fibonacci.py to maths/tests/test_fibonacci.py --- maths/{ => tests}/test_fibonacci.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename maths/{ => tests}/test_fibonacci.py (88%) diff --git a/maths/test_fibonacci.py b/maths/tests/test_fibonacci.py similarity index 88% rename from maths/test_fibonacci.py rename to maths/tests/test_fibonacci.py index 8da9d93b6a61..b444cfecd0c6 100644 --- a/maths/test_fibonacci.py +++ b/maths/tests/test_fibonacci.py @@ -1,8 +1,8 @@ """ 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 . +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. """ From ca3153aa7f57d5bd080e75b1ca359bcc42e1906b Mon Sep 17 00:00:00 2001 From: StephenGemin <45926479+StephenGemin@users.noreply.github.com> Date: Fri, 7 Jun 2019 11:43:55 -0400 Subject: [PATCH 07/11] Delete placeholder.py --- maths/tests/placeholder.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 maths/tests/placeholder.py diff --git a/maths/tests/placeholder.py b/maths/tests/placeholder.py deleted file mode 100644 index d4f031666c4c..000000000000 --- a/maths/tests/placeholder.py +++ /dev/null @@ -1 +0,0 @@ -# Just creating this so the folder isn't empty From 532e376f6e392e94a26f5a32cdba9365eaf0b35e Mon Sep 17 00:00:00 2001 From: StephenGemin <45926479+StephenGemin@users.noreply.github.com> Date: Fri, 7 Jun 2019 11:57:24 -0400 Subject: [PATCH 08/11] Create __init__.py --- maths/tests/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 maths/tests/__init__.py diff --git a/maths/tests/__init__.py b/maths/tests/__init__.py new file mode 100644 index 000000000000..2c4a6048556c --- /dev/null +++ b/maths/tests/__init__.py @@ -0,0 +1 @@ +from .. import fibonacci From 7c8ec0c810f8d8282bb7fce91941202ebcb205a8 Mon Sep 17 00:00:00 2001 From: StephenGemin <45926479+StephenGemin@users.noreply.github.com> Date: Fri, 7 Jun 2019 11:58:16 -0400 Subject: [PATCH 09/11] Update test_fibonacci.py --- maths/tests/test_fibonacci.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/tests/test_fibonacci.py b/maths/tests/test_fibonacci.py index b444cfecd0c6..7d36c755e346 100644 --- a/maths/tests/test_fibonacci.py +++ b/maths/tests/test_fibonacci.py @@ -8,7 +8,7 @@ """ import slash -import fibonacci +from .. import fibonacci default_fib = [0, 1, 1, 2, 3, 5, 8] From bca4ae8e1f829e02a8a7ea88a9ab4a649b745428 Mon Sep 17 00:00:00 2001 From: StephenGemin <45926479+StephenGemin@users.noreply.github.com> Date: Fri, 7 Jun 2019 14:36:58 -0400 Subject: [PATCH 10/11] Rename Maths/lucasSeries.py to maths/lucasSeries.py --- {Maths => maths}/lucasSeries.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {Maths => maths}/lucasSeries.py (100%) diff --git a/Maths/lucasSeries.py b/maths/lucasSeries.py similarity index 100% rename from Maths/lucasSeries.py rename to maths/lucasSeries.py From c368b2a06f578ac2f49452cdfe523b6b9b2f631e Mon Sep 17 00:00:00 2001 From: John Law Date: Sat, 8 Jun 2019 20:23:52 +0800 Subject: [PATCH 11/11] Update and rename Project Euler/Problem 01/sol5.py to project_euler/problem_01/sol6.py --- Project Euler/Problem 01/sol5.py | 8 -------- project_euler/problem_01/sol6.py | 9 +++++++++ 2 files changed, 9 insertions(+), 8 deletions(-) delete mode 100644 Project Euler/Problem 01/sol5.py create mode 100644 project_euler/problem_01/sol6.py diff --git a/Project Euler/Problem 01/sol5.py b/Project Euler/Problem 01/sol5.py deleted file mode 100644 index 0946bfaf18e7..000000000000 --- a/Project Euler/Problem 01/sol5.py +++ /dev/null @@ -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) diff --git a/project_euler/problem_01/sol6.py b/project_euler/problem_01/sol6.py new file mode 100644 index 000000000000..54c3073f3897 --- /dev/null +++ b/project_euler/problem_01/sol6.py @@ -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)