From 0435128cc097726bf54db2b34bdda61b546ecbe2 Mon Sep 17 00:00:00 2001 From: Ayush Bisht <61404154+ayushbisht2001@users.noreply.github.com> Date: Tue, 2 Mar 2021 03:00:16 +0530 Subject: [PATCH 1/4] Add geometric_mean.py (#4244) * geometric_mean3 * update-GM.PY * update-AM.PY * Revert "update-AM.PY" This reverts commit 11792ec9747bec5d00e51edcd462bf87150cdba9. --- maths/series/geometric_mean.py | 75 ++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 maths/series/geometric_mean.py diff --git a/maths/series/geometric_mean.py b/maths/series/geometric_mean.py new file mode 100644 index 000000000000..50ae54ad6574 --- /dev/null +++ b/maths/series/geometric_mean.py @@ -0,0 +1,75 @@ +""" +GEOMETRIC MEAN : https://en.wikipedia.org/wiki/Geometric_mean +""" + + +def is_geometric_series(series: list) -> bool: + """ + checking whether the input series is geometric series or not + + >>> is_geometric_series([2, 4, 8]) + True + >>> is_geometric_series([3, 6, 12, 24]) + True + >>> is_geometric_series([1, 2, 3]) + False + >>> is_geometric_series([0, 0, 3]) + False + + """ + if len(series) == 1: + return True + try: + common_ratio = series[1] / series[0] + for index in range(len(series) - 1): + if series[index + 1] / series[index] != common_ratio: + return False + except ZeroDivisionError: + return False + return True + + +def geometric_mean(series: list) -> float: + """ + return the geometric mean of series + + >>> geometric_mean([2, 4, 8]) + 3.9999999999999996 + >>> geometric_mean([3, 6, 12, 24]) + 8.48528137423857 + >>> geometric_mean([4, 8, 16]) + 7.999999999999999 + >>> geometric_mean(4) + Traceback (most recent call last): + ... + ValueError: Input series is not valid, valid series - [2, 4, 8] + >>> geometric_mean([1, 2, 3]) + Traceback (most recent call last): + ... + ValueError: Input list is not a geometric series + >>> geometric_mean([0, 2, 3]) + Traceback (most recent call last): + ... + ValueError: Input list is not a geometric series + >>> geometric_mean([]) + Traceback (most recent call last): + ... + ValueError: Input list must be a non empty list + + """ + if not isinstance(series, list): + raise ValueError("Input series is not valid, valid series - [2, 4, 8]") + if len(series) == 0: + raise ValueError("Input list must be a non empty list") + if not is_geometric_series(series): + raise ValueError("Input list is not a geometric series") + answer = 1 + for value in series: + answer *= value + return pow(answer, 1 / len(series)) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From a796ccf1ce2594bffdb938156987a0cbb16ee52e Mon Sep 17 00:00:00 2001 From: ulwlu Date: Tue, 2 Mar 2021 21:24:41 +0900 Subject: [PATCH 2/4] Add graham scan algorithm (#4205) * Add graham scan algorithm * Fix argument name p with point * Add tests in inner function * updating DIRECTORY.md * Fix graham scan for isort --profile=black Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 7 ++ other/graham_scan.py | 171 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+) create mode 100644 other/graham_scan.py diff --git a/DIRECTORY.md b/DIRECTORY.md index d487b39490ed..61e20eeb571d 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -30,6 +30,8 @@ * [Binary Count Trailing Zeros](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_count_trailing_zeros.py) * [Binary Or Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_or_operator.py) * [Binary Xor Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_xor_operator.py) + * [Count Number Of One Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/count_number_of_one_bits.py) + * [Reverse Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/reverse_bits.py) * [Single Bit Manipulation Operations](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/single_bit_manipulation_operations.py) ## Blockchain @@ -122,6 +124,7 @@ * [Fenwick Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/fenwick_tree.py) * [Lazy Segment Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/lazy_segment_tree.py) * [Lowest Common Ancestor](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/lowest_common_ancestor.py) + * [Merge Two Binary Trees](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/merge_two_binary_trees.py) * [Non Recursive Segment Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/non_recursive_segment_tree.py) * [Number Of Possible Binary Trees](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/number_of_possible_binary_trees.py) * [Red Black Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/red_black_tree.py) @@ -274,6 +277,7 @@ ## Graphics * [Bezier Curve](https://github.com/TheAlgorithms/Python/blob/master/graphics/bezier_curve.py) + * [Koch Snowflake](https://github.com/TheAlgorithms/Python/blob/master/graphics/koch_snowflake.py) * [Vector3 For 2D Rendering](https://github.com/TheAlgorithms/Python/blob/master/graphics/vector3_for_2d_rendering.py) ## Graphs @@ -520,6 +524,7 @@ * [Frequency Finder](https://github.com/TheAlgorithms/Python/blob/master/other/frequency_finder.py) * [Game Of Life](https://github.com/TheAlgorithms/Python/blob/master/other/game_of_life.py) * [Gauss Easter](https://github.com/TheAlgorithms/Python/blob/master/other/gauss_easter.py) + * [Graham Scan](https://github.com/TheAlgorithms/Python/blob/master/other/graham_scan.py) * [Greedy](https://github.com/TheAlgorithms/Python/blob/master/other/greedy.py) * [Integeration By Simpson Approx](https://github.com/TheAlgorithms/Python/blob/master/other/integeration_by_simpson_approx.py) * [Largest Subarray Sum](https://github.com/TheAlgorithms/Python/blob/master/other/largest_subarray_sum.py) @@ -840,6 +845,7 @@ * [Merge Insertion Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/merge_insertion_sort.py) * [Merge Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/merge_sort.py) * [Natural Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/natural_sort.py) + * [Odd Even Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_sort.py) * [Odd Even Transposition Parallel](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_transposition_parallel.py) * [Odd Even Transposition Single Threaded](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_transposition_single_threaded.py) * [Pancake Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/pancake_sort.py) @@ -856,6 +862,7 @@ * [Recursive Quick Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/recursive_quick_sort.py) * [Selection Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/selection_sort.py) * [Shell Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/shell_sort.py) + * [Slowsort](https://github.com/TheAlgorithms/Python/blob/master/sorts/slowsort.py) * [Stooge Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/stooge_sort.py) * [Strand Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/strand_sort.py) * [Tim Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/tim_sort.py) diff --git a/other/graham_scan.py b/other/graham_scan.py new file mode 100644 index 000000000000..67c5cd8ab9d8 --- /dev/null +++ b/other/graham_scan.py @@ -0,0 +1,171 @@ +""" +This is a pure Python implementation of the merge-insertion sort algorithm +Source: https://en.wikipedia.org/wiki/Graham_scan + +For doctests run following command: +python3 -m doctest -v graham_scan.py +""" + +from __future__ import annotations + +from collections import deque +from enum import Enum +from math import atan2, degrees +from sys import maxsize + + +def graham_scan(points: list[list[int, int]]) -> list[list[int, int]]: + """Pure implementation of graham scan algorithm in Python + + :param points: The unique points on coordinates. + :return: The points on convex hell. + + Examples: + >>> graham_scan([(9, 6), (3, 1), (0, 0), (5, 5), (5, 2), (7, 0), (3, 3), (1, 4)]) + [(0, 0), (7, 0), (9, 6), (5, 5), (1, 4)] + + >>> graham_scan([(0, 0), (1, 0), (1, 1), (0, 1)]) + [(0, 0), (1, 0), (1, 1), (0, 1)] + + >>> graham_scan([(0, 0), (1, 1), (2, 2), (3, 3), (-1, 2)]) + [(0, 0), (1, 1), (2, 2), (3, 3), (-1, 2)] + + >>> graham_scan([(-100, 20), (99, 3), (1, 10000001), (5133186, -25), (-66, -4)]) + [(5133186, -25), (1, 10000001), (-100, 20), (-66, -4)] + """ + + if len(points) <= 2: + # There is no convex hull + raise ValueError("graham_scan: argument must contain more than 3 points.") + if len(points) == 3: + return points + # find the lowest and the most left point + minidx = 0 + miny, minx = maxsize, maxsize + for i, point in enumerate(points): + x = point[0] + y = point[1] + if y < miny: + miny = y + minx = x + minidx = i + if y == miny: + if x < minx: + minx = x + minidx = i + + # remove the lowest and the most left point from points for preparing for sort + points.pop(minidx) + + def angle_comparer(point: list[int, int], minx: int, miny: int) -> float: + """Return the angle toward to point from (minx, miny) + + :param point: The target point + minx: The starting point's x + miny: The starting point's y + :return: the angle + + Examples: + >>> angle_comparer([1,1], 0, 0) + 45.0 + + >>> angle_comparer([100,1], 10, 10) + -5.710593137499642 + + >>> angle_comparer([5,5], 2, 3) + 33.690067525979785 + """ + # sort the points accorgind to the angle from the lowest and the most left point + x = point[0] + y = point[1] + angle = degrees(atan2(y - miny, x - minx)) + return angle + + sorted_points = sorted(points, key=lambda point: angle_comparer(point, minx, miny)) + # This insert actually costs complexity, + # and you should insteadly add (minx, miny) into stack later. + # I'm using insert just for easy understanding. + sorted_points.insert(0, (minx, miny)) + + # traversal from the lowest and the most left point in anti-clockwise direction + # if direction gets right, the previous point is not the convex hull. + class Direction(Enum): + left = 1 + straight = 2 + right = 3 + + def check_direction( + starting: list[int, int], via: list[int, int], target: list[int, int] + ) -> Direction: + """Return the direction toward to the line from via to target from starting + + :param starting: The starting point + via: The via point + target: The target point + :return: the Direction + + Examples: + >>> check_direction([1,1], [2,2], [3,3]) + Direction.straight + + >>> check_direction([60,1], [-50,199], [30,2]) + Direction.left + + >>> check_direction([0,0], [5,5], [10,0]) + Direction.right + """ + x0, y0 = starting + x1, y1 = via + x2, y2 = target + via_angle = degrees(atan2(y1 - y0, x1 - x0)) + if via_angle < 0: + via_angle += 360 + target_angle = degrees(atan2(y2 - y0, x2 - x0)) + if target_angle < 0: + target_angle += 360 + # t- + # \ \ + # \ v + # \| + # s + # via_angle is always lower than target_angle, if direction is left. + # If they are same, it means they are on a same line of convex hull. + if target_angle > via_angle: + return Direction.left + if target_angle == via_angle: + return Direction.straight + if target_angle < via_angle: + return Direction.right + + stack = deque() + stack.append(sorted_points[0]) + stack.append(sorted_points[1]) + stack.append(sorted_points[2]) + # In any ways, the first 3 points line are towards left. + # Because we sort them the angle from minx, miny. + current_direction = Direction.left + + for i in range(3, len(sorted_points)): + while True: + starting = stack[-2] + via = stack[-1] + target = sorted_points[i] + next_direction = check_direction(starting, via, target) + + if next_direction == Direction.left: + current_direction = Direction.left + break + if next_direction == Direction.straight: + if current_direction == Direction.left: + # We keep current_direction as left. + # Because if the straight line keeps as straight, + # we want to know if this straight line is towards left. + break + elif current_direction == Direction.right: + # If the straight line is towards right, + # every previous points on those straigh line is not convex hull. + stack.pop() + if next_direction == Direction.right: + stack.pop() + stack.append(sorted_points[i]) + return list(stack) From ecf9b8164fc3046ad5e6bbabb4abf3ac6a8a3cbb Mon Sep 17 00:00:00 2001 From: fpringle Date: Sat, 6 Mar 2021 14:29:52 +0100 Subject: [PATCH 3/4] Added solution for Project Euler problem 109 (#4080) * Added solution for Project Euler problem 109 * New subscriptable builtin types * updating DIRECTORY.md Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 6 ++ project_euler/problem_109/__init__.py | 0 project_euler/problem_109/sol1.py | 89 +++++++++++++++++++++++++++ 3 files changed, 95 insertions(+) create mode 100644 project_euler/problem_109/__init__.py create mode 100644 project_euler/problem_109/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index 61e20eeb571d..dfb673dea829 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -29,6 +29,8 @@ * [Binary Count Setbits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_count_setbits.py) * [Binary Count Trailing Zeros](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_count_trailing_zeros.py) * [Binary Or Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_or_operator.py) + * [Binary Shifts](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_shifts.py) + * [Binary Twos Complement](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_twos_complement.py) * [Binary Xor Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_xor_operator.py) * [Count Number Of One Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/count_number_of_one_bits.py) * [Reverse Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/reverse_bits.py) @@ -278,6 +280,7 @@ ## Graphics * [Bezier Curve](https://github.com/TheAlgorithms/Python/blob/master/graphics/bezier_curve.py) * [Koch Snowflake](https://github.com/TheAlgorithms/Python/blob/master/graphics/koch_snowflake.py) + * [Mandelbrot](https://github.com/TheAlgorithms/Python/blob/master/graphics/mandelbrot.py) * [Vector3 For 2D Rendering](https://github.com/TheAlgorithms/Python/blob/master/graphics/vector3_for_2d_rendering.py) ## Graphs @@ -469,6 +472,7 @@ * [Runge Kutta](https://github.com/TheAlgorithms/Python/blob/master/maths/runge_kutta.py) * [Segmented Sieve](https://github.com/TheAlgorithms/Python/blob/master/maths/segmented_sieve.py) * Series + * [Geometric Mean](https://github.com/TheAlgorithms/Python/blob/master/maths/series/geometric_mean.py) * [Geometric Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/geometric_series.py) * [Harmonic Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/harmonic_series.py) * [P Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/p_series.py) @@ -757,6 +761,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_102/sol1.py) * Problem 107 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_107/sol1.py) + * Problem 109 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_109/sol1.py) * Problem 112 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_112/sol1.py) * Problem 113 diff --git a/project_euler/problem_109/__init__.py b/project_euler/problem_109/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/project_euler/problem_109/sol1.py b/project_euler/problem_109/sol1.py new file mode 100644 index 000000000000..91c71eb9f4cb --- /dev/null +++ b/project_euler/problem_109/sol1.py @@ -0,0 +1,89 @@ +""" +In the game of darts a player throws three darts at a target board which is +split into twenty equal sized sections numbered one to twenty. + +The score of a dart is determined by the number of the region that the dart +lands in. A dart landing outside the red/green outer ring scores zero. The black +and cream regions inside this ring represent single scores. However, the red/green +outer ring and middle ring score double and treble scores respectively. + +At the centre of the board are two concentric circles called the bull region, or +bulls-eye. The outer bull is worth 25 points and the inner bull is a double, +worth 50 points. + +There are many variations of rules but in the most popular game the players will +begin with a score 301 or 501 and the first player to reduce their running total +to zero is a winner. However, it is normal to play a "doubles out" system, which +means that the player must land a double (including the double bulls-eye at the +centre of the board) on their final dart to win; any other dart that would reduce +their running total to one or lower means the score for that set of three darts +is "bust". + +When a player is able to finish on their current score it is called a "checkout" +and the highest checkout is 170: T20 T20 D25 (two treble 20s and double bull). + +There are exactly eleven distinct ways to checkout on a score of 6: + +D3 +D1 D2 +S2 D2 +D2 D1 +S4 D1 +S1 S1 D2 +S1 T1 D1 +S1 S3 D1 +D1 D1 D1 +D1 S2 D1 +S2 S2 D1 + +Note that D1 D2 is considered different to D2 D1 as they finish on different +doubles. However, the combination S1 T1 D1 is considered the same as T1 S1 D1. + +In addition we shall not include misses in considering combinations; for example, +D3 is the same as 0 D3 and 0 0 D3. + +Incredibly there are 42336 distinct ways of checking out in total. + +How many distinct ways can a player checkout with a score less than 100? + +Solution: + We first construct a list of the possible dart values, separated by type. + We then iterate through the doubles, followed by the possible 2 following throws. + If the total of these three darts is less than the given limit, we increment + the counter. +""" + +from itertools import combinations_with_replacement + + +def solution(limit: int = 100) -> int: + """ + Count the number of distinct ways a player can checkout with a score + less than limit. + >>> solution(171) + 42336 + >>> solution(50) + 12577 + """ + singles: list[int] = [x for x in range(1, 21)] + [25] + doubles: list[int] = [2 * x for x in range(1, 21)] + [50] + triples: list[int] = [3 * x for x in range(1, 21)] + all_values: list[int] = singles + doubles + triples + [0] + + num_checkouts: int = 0 + double: int + throw1: int + throw2: int + checkout_total: int + + for double in doubles: + for throw1, throw2 in combinations_with_replacement(all_values, 2): + checkout_total = double + throw1 + throw2 + if checkout_total < limit: + num_checkouts += 1 + + return num_checkouts + + +if __name__ == "__main__": + print(f"{solution() = }") From ced83bed2cda5a1a4353f3ced2871a884d380879 Mon Sep 17 00:00:00 2001 From: Ayush Bisht <61404154+ayushbisht2001@users.noreply.github.com> Date: Fri, 12 Mar 2021 12:55:54 +0530 Subject: [PATCH 4/4] Add arithmetic_mean.py (#4243) * arithmetic_mean * arithmetic_mean * checks * checked * Revert "checked" This reverts commit 3913a39ae2c4ee183443eed67ee7427e3d322ad4. * checks-3 * update-1 --- maths/series/arithmetic_mean.py | 66 +++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 maths/series/arithmetic_mean.py diff --git a/maths/series/arithmetic_mean.py b/maths/series/arithmetic_mean.py new file mode 100644 index 000000000000..b5d64b63ac3f --- /dev/null +++ b/maths/series/arithmetic_mean.py @@ -0,0 +1,66 @@ +""" +ARITHMETIC MEAN : https://en.wikipedia.org/wiki/Arithmetic_mean + +""" + + +def is_arithmetic_series(series: list) -> bool: + """ + checking whether the input series is arithmetic series or not + + >>> is_arithmetic_series([2, 4, 6]) + True + >>> is_arithmetic_series([3, 6, 12, 24]) + False + >>> is_arithmetic_series([1, 2, 3]) + True + """ + if len(series) == 1: + return True + common_diff = series[1] - series[0] + for index in range(len(series) - 1): + if series[index + 1] - series[index] != common_diff: + return False + return True + + +def arithmetic_mean(series: list) -> float: + """ + return the arithmetic mean of series + + >>> arithmetic_mean([2, 4, 6]) + 4.0 + >>> arithmetic_mean([3, 6, 9, 12]) + 7.5 + >>> arithmetic_mean(4) + Traceback (most recent call last): + ... + ValueError: Input series is not valid, valid series - [2, 4, 6] + >>> arithmetic_mean([4, 8, 1]) + Traceback (most recent call last): + ... + ValueError: Input list is not an arithmetic series + >>> arithmetic_mean([1, 2, 3]) + 2.0 + >>> arithmetic_mean([]) + Traceback (most recent call last): + ... + ValueError: Input list must be a non empty list + + """ + if not isinstance(series, list): + raise ValueError("Input series is not valid, valid series - [2, 4, 6]") + if len(series) == 0: + raise ValueError("Input list must be a non empty list") + if not is_arithmetic_series(series): + raise ValueError("Input list is not an arithmetic series") + answer = 0 + for val in series: + answer += val + return answer / len(series) + + +if __name__ == "__main__": + import doctest + + doctest.testmod()