From baf7a8da1b9adfe424138a3bbc4dbf358387d252 Mon Sep 17 00:00:00 2001 From: Sharan Krishnan Date: Mon, 13 Jan 2020 19:02:24 +1100 Subject: [PATCH 1/8] A recursive insertion sort --- sorts/recursive_insertion_sort.py | 55 +++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 sorts/recursive_insertion_sort.py diff --git a/sorts/recursive_insertion_sort.py b/sorts/recursive_insertion_sort.py new file mode 100644 index 000000000000..1cd30c2e5738 --- /dev/null +++ b/sorts/recursive_insertion_sort.py @@ -0,0 +1,55 @@ +""" +A recursive implementation of the insertion sort algorithm +""" + +def rec_insertion_sort(collection, n): + """ + Given a collection of numbers and its length, sorts the collections + in ascending order + + :param collection: A mutable collection of heterogenous, comparable elements + :param n: The length of collections + + >>> col = [1, 2, 1] + >>> rec_insertion_sort(col, len(col)) + >>> print(col) + [1, 1, 2] + + >>> col = [2, 1, 0, -1, -2] + >>> rec_insertion_sort(col, len(col)) + >>> print(col) + [-2, -1, 0, 1, 2] + + >>> col = [1] + >>> rec_insertion_sort(col, len(col)) + >>> print(col) + [1] + """ + + + #Checks if the entire collection has been sorted + if len(collection) <= 1 or n <= 1: + return + + + data_swap(collection, n-1) + rec_insertion_sort(collection, n-1) + +def data_swap(collection, index): + + #Checks order between adjacent elements + if index >= len(collection) or collection[index - 1] <= collection[index]: + return + + #Swaps adjacent elements since they are not in ascending order + collection[index - 1], collection[index] = ( + collection[index], collection[index - 1] + ) + + data_swap(collection, index + 1) + +if __name__ == "__main__": + numbers = input("Enter integers seperated by spaces: ") + numbers = [int(num) for num in numbers.split()] + rec_insertion_sort(numbers, len(numbers)) + print(numbers) From 0af0c940e16581c6218ddc8eb45f38bbcffcbcb1 Mon Sep 17 00:00:00 2001 From: Sharan Krishnan Date: Mon, 13 Jan 2020 20:27:17 +1100 Subject: [PATCH 2/8] added doctests and typehints --- sorts/recursive_insertion_sort.py | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/sorts/recursive_insertion_sort.py b/sorts/recursive_insertion_sort.py index 1cd30c2e5738..a8bd2b9114ad 100644 --- a/sorts/recursive_insertion_sort.py +++ b/sorts/recursive_insertion_sort.py @@ -2,12 +2,14 @@ A recursive implementation of the insertion sort algorithm """ -def rec_insertion_sort(collection, n): +from typing import List + +def rec_insertion_sort(collection: List, n: int): """ Given a collection of numbers and its length, sorts the collections in ascending order - :param collection: A mutable collection of heterogenous, comparable elements + :param collection: A mutable collection of comparable elements :param n: The length of collections >>> col = [1, 2, 1] @@ -25,18 +27,33 @@ def rec_insertion_sort(collection, n): >>> print(col) [1] """ - - #Checks if the entire collection has been sorted if len(collection) <= 1 or n <= 1: return - data_swap(collection, n-1) + insert_next(collection, n-1) rec_insertion_sort(collection, n-1) -def data_swap(collection, index): +def insert_next(collection: List, index: int): + """ + Inserts the '(index-1)th' element into place + + >>> col = [3, 2, 4, 2] + >>> insert_next(col, 1) + >>> print(col) + [2, 3, 4, 2] + + >>> col = [3, 2, 3] + >>> insert_next(col, 2) + >>> print(col) + [3, 2, 3] + >>> col = [] + >>> insert_next(col, 1) + >>> print(col) + [] + """ #Checks order between adjacent elements if index >= len(collection) or collection[index - 1] <= collection[index]: return @@ -46,7 +63,7 @@ def data_swap(collection, index): collection[index], collection[index - 1] ) - data_swap(collection, index + 1) + insert_next(collection, index + 1) if __name__ == "__main__": numbers = input("Enter integers seperated by spaces: ") From 1445753d4aa43e84dffd5367532def4f736357a1 Mon Sep 17 00:00:00 2001 From: Sharan Krishnan Date: Fri, 17 Jan 2020 15:47:20 +1100 Subject: [PATCH 3/8] Added arc length and numerical integration calculators --- maths/line_length.py | 62 ++++++++++++++++++++++++++++++++++ maths/numerical_integration.py | 62 ++++++++++++++++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 maths/line_length.py create mode 100644 maths/numerical_integration.py diff --git a/maths/line_length.py b/maths/line_length.py new file mode 100644 index 000000000000..d3cd2a07a759 --- /dev/null +++ b/maths/line_length.py @@ -0,0 +1,62 @@ +from typing import Callable, Union +import math as m + +def line_length(fnc: Callable[[Union[int, float]], Union[int, float]], + x_start: Union[int, float], + x_end: Union[int, float], + steps: int = 100) -> float: + + """ + Approximates the arc length of a line segment by treating the curve as a + sequence of linear lines and summing their lengths + :param fnc: a function which defines a curve + :param x_start: left end point to indicate the start of line segment + :param x_end: right end point to indicate end of line segment + :param steps: an accuracy gauge; more steps increases accuracy + :return: a float representing the length of the curve + + >>> def f(x): + ... return x + >>> '%.6f' % line_length(f, 0, 1, 10) + '1.414213' + + >>> def f(x): + ... return 1 + >>> '%.6f' % line_length(f, -5.5, 4.5, 100) + '10.000000' + + >>> def f(x): + ... return m.sin(5 * x) + m.cos(10 * x) + x * x/10 + >>> '%.6f' % line_length(f, 0.0, 10.0, 10000) + '69.534930' + """ + + x1 = x_start + fx1 = fnc(x_start) + length = 0 + + for i in range(steps): + + #approximates curve as a sequence of linear lines and sums their length + x2 = (x_end - x_start) / steps + x1 + fx2 = fnc(x2) + length += m.hypot(x2 - x1, fx2 - fx1) + + #increment step + x1 = x2 + fx1 = fx2 + + return length + +if __name__ == "__main__": + + def f(x): + return m.sin(10*x) + + print("f(x) = sin(10 * x)") + print("The length of the curve from x = -10 to x = 10 is:") + i = 10 + while i <= 100000: + length = line_length(f, -10, 10, i) + print("With {} steps: {}".format(i, length)) + i *= 10 diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py new file mode 100644 index 000000000000..3a4e5aa01313 --- /dev/null +++ b/maths/numerical_integration.py @@ -0,0 +1,62 @@ +""" +Approximates the area under the curve using the trapezoidal rule +""" + +from typing import Callable, Union + +def trapezoidal_area(fnc: Callable[[Union[int, float]], Union[int, float]], + x_start: Union[int, float], + x_end: Union[int, float], + steps: int = 100) -> float: + + """ + Treats curve as a collection of linear lines and sums the area of the + trapezium shape they form + :param fnc: a function which defines a curve + :param x_start: left end point to indicate the start of line segment + :param x_end: right end point to indicate end of line segment + :param steps: an accuracy gauge; more steps increases the accuracy + :return: a float representing the length of the curve + + >>> def f(x): + ... return 5 + >>> '%.3f' % trapezoidal_area(f, 12.0, 14.0, 1000) + '10.000' + + >>> def f(x): + ... return 9*x**2 + >>> '%.4f' % trapezoidal_area(f, -4.0, 0, 10000) + '192.0000' + + >>> '%.4f' % trapezoidal_area(f, -4.0, 4.0, 10000) + '384.0000' + """ + x1 = x_start + fx1 = fnc(x_start) + area = 0 + + for i in range(steps): + + #approx small segments of curve as linear and solve for trapezoidal area + x2 = (x_end - x_start)/steps + x1 + fx2 = fnc(x2) + area += abs(fx2 + fx1) * (x2 - x1)/2 + + #increment step + x1 = x2 + fx1 = fx2 + return area + + +if __name__ == "__main__": + + def f(x): + return x**3 + + print("f(x) = x^3") + print("The area between the curve, x = -10, x = 10 and the x axis is:") + i = 10 + while i <= 100000: + area = trapezoidal_area(f, -5, 5, i) + print("with {} steps: {}".format(i, area)) + i*=10 From 1129e09cb16a5ae5acfd8f06f2f871f602041029 Mon Sep 17 00:00:00 2001 From: Sharan Krishnan Date: Fri, 17 Jan 2020 16:13:42 +1100 Subject: [PATCH 4/8] fixed doc test --- maths/line_length.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maths/line_length.py b/maths/line_length.py index d3cd2a07a759..71826aef37b9 100644 --- a/maths/line_length.py +++ b/maths/line_length.py @@ -18,7 +18,7 @@ def line_length(fnc: Callable[[Union[int, float]], Union[int, float]], >>> def f(x): ... return x >>> '%.6f' % line_length(f, 0, 1, 10) - '1.414213' + '1.414214' >>> def f(x): ... return 1 From 52c1a58dfec9d104e58b141fc5921c947795ddee Mon Sep 17 00:00:00 2001 From: Sharan Krishnan Date: Fri, 17 Jan 2020 16:25:01 +1100 Subject: [PATCH 5/8] Fixed some conversion errors --- maths/line_length.py | 2 +- maths/numerical_integration.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/maths/line_length.py b/maths/line_length.py index 71826aef37b9..3e4842e8104d 100644 --- a/maths/line_length.py +++ b/maths/line_length.py @@ -33,7 +33,7 @@ def line_length(fnc: Callable[[Union[int, float]], Union[int, float]], x1 = x_start fx1 = fnc(x_start) - length = 0 + length = 0.0 for i in range(steps): diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py index 3a4e5aa01313..310a1a9fd53e 100644 --- a/maths/numerical_integration.py +++ b/maths/numerical_integration.py @@ -33,7 +33,7 @@ def trapezoidal_area(fnc: Callable[[Union[int, float]], Union[int, float]], """ x1 = x_start fx1 = fnc(x_start) - area = 0 + area = 0.0 for i in range(steps): From a258cb1af2047d3686a519814045e58315ed2358 Mon Sep 17 00:00:00 2001 From: Sharan Krishnan Date: Fri, 17 Jan 2020 16:34:46 +1100 Subject: [PATCH 6/8] Fixed some commenting --- maths/line_length.py | 4 +- maths/numerical_integration.py | 5 ++- sorts/recursive_insertion_sort.py | 72 ------------------------------- 3 files changed, 5 insertions(+), 76 deletions(-) delete mode 100644 sorts/recursive_insertion_sort.py diff --git a/maths/line_length.py b/maths/line_length.py index 3e4842e8104d..2be8e133822b 100644 --- a/maths/line_length.py +++ b/maths/line_length.py @@ -37,12 +37,12 @@ def line_length(fnc: Callable[[Union[int, float]], Union[int, float]], for i in range(steps): - #approximates curve as a sequence of linear lines and sums their length + # Approximates curve as a sequence of linear lines and sums their length x2 = (x_end - x_start) / steps + x1 fx2 = fnc(x2) length += m.hypot(x2 - x1, fx2 - fx1) - #increment step + # Increment step x1 = x2 fx1 = fx2 diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py index 310a1a9fd53e..55026f0d627f 100644 --- a/maths/numerical_integration.py +++ b/maths/numerical_integration.py @@ -37,12 +37,13 @@ def trapezoidal_area(fnc: Callable[[Union[int, float]], Union[int, float]], for i in range(steps): - #approx small segments of curve as linear and solve for trapezoidal area + # Approximates small segments of curve as linear and solve + # for trapezoidal area x2 = (x_end - x_start)/steps + x1 fx2 = fnc(x2) area += abs(fx2 + fx1) * (x2 - x1)/2 - #increment step + # Increment step x1 = x2 fx1 = fx2 return area diff --git a/sorts/recursive_insertion_sort.py b/sorts/recursive_insertion_sort.py deleted file mode 100644 index a8bd2b9114ad..000000000000 --- a/sorts/recursive_insertion_sort.py +++ /dev/null @@ -1,72 +0,0 @@ -""" -A recursive implementation of the insertion sort algorithm -""" - -from typing import List - -def rec_insertion_sort(collection: List, n: int): - """ - Given a collection of numbers and its length, sorts the collections - in ascending order - - :param collection: A mutable collection of comparable elements - :param n: The length of collections - - >>> col = [1, 2, 1] - >>> rec_insertion_sort(col, len(col)) - >>> print(col) - [1, 1, 2] - - >>> col = [2, 1, 0, -1, -2] - >>> rec_insertion_sort(col, len(col)) - >>> print(col) - [-2, -1, 0, 1, 2] - - >>> col = [1] - >>> rec_insertion_sort(col, len(col)) - >>> print(col) - [1] - """ - #Checks if the entire collection has been sorted - if len(collection) <= 1 or n <= 1: - return - - - insert_next(collection, n-1) - rec_insertion_sort(collection, n-1) - -def insert_next(collection: List, index: int): - """ - Inserts the '(index-1)th' element into place - - >>> col = [3, 2, 4, 2] - >>> insert_next(col, 1) - >>> print(col) - [2, 3, 4, 2] - - >>> col = [3, 2, 3] - >>> insert_next(col, 2) - >>> print(col) - [3, 2, 3] - - >>> col = [] - >>> insert_next(col, 1) - >>> print(col) - [] - """ - #Checks order between adjacent elements - if index >= len(collection) or collection[index - 1] <= collection[index]: - return - - #Swaps adjacent elements since they are not in ascending order - collection[index - 1], collection[index] = ( - collection[index], collection[index - 1] - ) - - insert_next(collection, index + 1) - -if __name__ == "__main__": - numbers = input("Enter integers seperated by spaces: ") - numbers = [int(num) for num in numbers.split()] - rec_insertion_sort(numbers, len(numbers)) - print(numbers) From 3e60489f18fc12974ab0b0f14ad9700f4e718049 Mon Sep 17 00:00:00 2001 From: Sharan Krishnan Date: Fri, 17 Jan 2020 16:43:11 +1100 Subject: [PATCH 7/8] Deleted numerical integration to allow 1 file per push --- maths/numerical_integration.py | 63 ---------------------------------- 1 file changed, 63 deletions(-) delete mode 100644 maths/numerical_integration.py diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py deleted file mode 100644 index 55026f0d627f..000000000000 --- a/maths/numerical_integration.py +++ /dev/null @@ -1,63 +0,0 @@ -""" -Approximates the area under the curve using the trapezoidal rule -""" - -from typing import Callable, Union - -def trapezoidal_area(fnc: Callable[[Union[int, float]], Union[int, float]], - x_start: Union[int, float], - x_end: Union[int, float], - steps: int = 100) -> float: - - """ - Treats curve as a collection of linear lines and sums the area of the - trapezium shape they form - :param fnc: a function which defines a curve - :param x_start: left end point to indicate the start of line segment - :param x_end: right end point to indicate end of line segment - :param steps: an accuracy gauge; more steps increases the accuracy - :return: a float representing the length of the curve - - >>> def f(x): - ... return 5 - >>> '%.3f' % trapezoidal_area(f, 12.0, 14.0, 1000) - '10.000' - - >>> def f(x): - ... return 9*x**2 - >>> '%.4f' % trapezoidal_area(f, -4.0, 0, 10000) - '192.0000' - - >>> '%.4f' % trapezoidal_area(f, -4.0, 4.0, 10000) - '384.0000' - """ - x1 = x_start - fx1 = fnc(x_start) - area = 0.0 - - for i in range(steps): - - # Approximates small segments of curve as linear and solve - # for trapezoidal area - x2 = (x_end - x_start)/steps + x1 - fx2 = fnc(x2) - area += abs(fx2 + fx1) * (x2 - x1)/2 - - # Increment step - x1 = x2 - fx1 = fx2 - return area - - -if __name__ == "__main__": - - def f(x): - return x**3 - - print("f(x) = x^3") - print("The area between the curve, x = -10, x = 10 and the x axis is:") - i = 10 - while i <= 100000: - area = trapezoidal_area(f, -5, 5, i) - print("with {} steps: {}".format(i, area)) - i*=10 From 4ab2263240b50ea988ff2e468f0c047700bb3e27 Mon Sep 17 00:00:00 2001 From: Sharan Krishnan Date: Fri, 17 Jan 2020 18:02:47 +1100 Subject: [PATCH 8/8] Changed string formatting method --- maths/line_length.py | 9 +++-- maths/numerical_integration.py | 63 ++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 maths/numerical_integration.py diff --git a/maths/line_length.py b/maths/line_length.py index 2be8e133822b..8737a863b902 100644 --- a/maths/line_length.py +++ b/maths/line_length.py @@ -17,17 +17,17 @@ def line_length(fnc: Callable[[Union[int, float]], Union[int, float]], >>> def f(x): ... return x - >>> '%.6f' % line_length(f, 0, 1, 10) + >>> f"{line_length(f, 0, 1, 10):.6f}" '1.414214' >>> def f(x): ... return 1 - >>> '%.6f' % line_length(f, -5.5, 4.5, 100) + >>> f"{line_length(f, -5.5, 4.5):.6f}" '10.000000' >>> def f(x): ... return m.sin(5 * x) + m.cos(10 * x) + x * x/10 - >>> '%.6f' % line_length(f, 0.0, 10.0, 10000) + >>> f"{line_length(f, 0.0, 10.0, 10000):.6f}" '69.534930' """ @@ -57,6 +57,5 @@ def f(x): print("The length of the curve from x = -10 to x = 10 is:") i = 10 while i <= 100000: - length = line_length(f, -10, 10, i) - print("With {} steps: {}".format(i, length)) + print(f"With {i} steps: {line_length(f, -10, 10, i)}") i *= 10 diff --git a/maths/numerical_integration.py b/maths/numerical_integration.py new file mode 100644 index 000000000000..55026f0d627f --- /dev/null +++ b/maths/numerical_integration.py @@ -0,0 +1,63 @@ +""" +Approximates the area under the curve using the trapezoidal rule +""" + +from typing import Callable, Union + +def trapezoidal_area(fnc: Callable[[Union[int, float]], Union[int, float]], + x_start: Union[int, float], + x_end: Union[int, float], + steps: int = 100) -> float: + + """ + Treats curve as a collection of linear lines and sums the area of the + trapezium shape they form + :param fnc: a function which defines a curve + :param x_start: left end point to indicate the start of line segment + :param x_end: right end point to indicate end of line segment + :param steps: an accuracy gauge; more steps increases the accuracy + :return: a float representing the length of the curve + + >>> def f(x): + ... return 5 + >>> '%.3f' % trapezoidal_area(f, 12.0, 14.0, 1000) + '10.000' + + >>> def f(x): + ... return 9*x**2 + >>> '%.4f' % trapezoidal_area(f, -4.0, 0, 10000) + '192.0000' + + >>> '%.4f' % trapezoidal_area(f, -4.0, 4.0, 10000) + '384.0000' + """ + x1 = x_start + fx1 = fnc(x_start) + area = 0.0 + + for i in range(steps): + + # Approximates small segments of curve as linear and solve + # for trapezoidal area + x2 = (x_end - x_start)/steps + x1 + fx2 = fnc(x2) + area += abs(fx2 + fx1) * (x2 - x1)/2 + + # Increment step + x1 = x2 + fx1 = fx2 + return area + + +if __name__ == "__main__": + + def f(x): + return x**3 + + print("f(x) = x^3") + print("The area between the curve, x = -10, x = 10 and the x axis is:") + i = 10 + while i <= 100000: + area = trapezoidal_area(f, -5, 5, i) + print("with {} steps: {}".format(i, area)) + i*=10