Skip to content

Commit 8467a83

Browse files
authored
Merge pull request #4 from TheAlgorithms/master
update fork
2 parents 681d30c + ced83be commit 8467a83

File tree

6 files changed

+414
-0
lines changed

6 files changed

+414
-0
lines changed

DIRECTORY.md

+13
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@
2929
* [Binary Count Setbits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_count_setbits.py)
3030
* [Binary Count Trailing Zeros](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_count_trailing_zeros.py)
3131
* [Binary Or Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_or_operator.py)
32+
* [Binary Shifts](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_shifts.py)
33+
* [Binary Twos Complement](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_twos_complement.py)
3234
* [Binary Xor Operator](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/binary_xor_operator.py)
35+
* [Count Number Of One Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/count_number_of_one_bits.py)
36+
* [Reverse Bits](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/reverse_bits.py)
3337
* [Single Bit Manipulation Operations](https://github.com/TheAlgorithms/Python/blob/master/bit_manipulation/single_bit_manipulation_operations.py)
3438

3539
## Blockchain
@@ -122,6 +126,7 @@
122126
* [Fenwick Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/fenwick_tree.py)
123127
* [Lazy Segment Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/lazy_segment_tree.py)
124128
* [Lowest Common Ancestor](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/lowest_common_ancestor.py)
129+
* [Merge Two Binary Trees](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/merge_two_binary_trees.py)
125130
* [Non Recursive Segment Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/non_recursive_segment_tree.py)
126131
* [Number Of Possible Binary Trees](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/number_of_possible_binary_trees.py)
127132
* [Red Black Tree](https://github.com/TheAlgorithms/Python/blob/master/data_structures/binary_tree/red_black_tree.py)
@@ -274,6 +279,8 @@
274279

275280
## Graphics
276281
* [Bezier Curve](https://github.com/TheAlgorithms/Python/blob/master/graphics/bezier_curve.py)
282+
* [Koch Snowflake](https://github.com/TheAlgorithms/Python/blob/master/graphics/koch_snowflake.py)
283+
* [Mandelbrot](https://github.com/TheAlgorithms/Python/blob/master/graphics/mandelbrot.py)
277284
* [Vector3 For 2D Rendering](https://github.com/TheAlgorithms/Python/blob/master/graphics/vector3_for_2d_rendering.py)
278285

279286
## Graphs
@@ -465,6 +472,7 @@
465472
* [Runge Kutta](https://github.com/TheAlgorithms/Python/blob/master/maths/runge_kutta.py)
466473
* [Segmented Sieve](https://github.com/TheAlgorithms/Python/blob/master/maths/segmented_sieve.py)
467474
* Series
475+
* [Geometric Mean](https://github.com/TheAlgorithms/Python/blob/master/maths/series/geometric_mean.py)
468476
* [Geometric Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/geometric_series.py)
469477
* [Harmonic Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/harmonic_series.py)
470478
* [P Series](https://github.com/TheAlgorithms/Python/blob/master/maths/series/p_series.py)
@@ -520,6 +528,7 @@
520528
* [Frequency Finder](https://github.com/TheAlgorithms/Python/blob/master/other/frequency_finder.py)
521529
* [Game Of Life](https://github.com/TheAlgorithms/Python/blob/master/other/game_of_life.py)
522530
* [Gauss Easter](https://github.com/TheAlgorithms/Python/blob/master/other/gauss_easter.py)
531+
* [Graham Scan](https://github.com/TheAlgorithms/Python/blob/master/other/graham_scan.py)
523532
* [Greedy](https://github.com/TheAlgorithms/Python/blob/master/other/greedy.py)
524533
* [Integeration By Simpson Approx](https://github.com/TheAlgorithms/Python/blob/master/other/integeration_by_simpson_approx.py)
525534
* [Largest Subarray Sum](https://github.com/TheAlgorithms/Python/blob/master/other/largest_subarray_sum.py)
@@ -752,6 +761,8 @@
752761
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_102/sol1.py)
753762
* Problem 107
754763
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_107/sol1.py)
764+
* Problem 109
765+
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_109/sol1.py)
755766
* Problem 112
756767
* [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_112/sol1.py)
757768
* Problem 113
@@ -840,6 +851,7 @@
840851
* [Merge Insertion Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/merge_insertion_sort.py)
841852
* [Merge Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/merge_sort.py)
842853
* [Natural Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/natural_sort.py)
854+
* [Odd Even Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_sort.py)
843855
* [Odd Even Transposition Parallel](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_transposition_parallel.py)
844856
* [Odd Even Transposition Single Threaded](https://github.com/TheAlgorithms/Python/blob/master/sorts/odd_even_transposition_single_threaded.py)
845857
* [Pancake Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/pancake_sort.py)
@@ -856,6 +868,7 @@
856868
* [Recursive Quick Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/recursive_quick_sort.py)
857869
* [Selection Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/selection_sort.py)
858870
* [Shell Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/shell_sort.py)
871+
* [Slowsort](https://github.com/TheAlgorithms/Python/blob/master/sorts/slowsort.py)
859872
* [Stooge Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/stooge_sort.py)
860873
* [Strand Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/strand_sort.py)
861874
* [Tim Sort](https://github.com/TheAlgorithms/Python/blob/master/sorts/tim_sort.py)

maths/series/arithmetic_mean.py

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
"""
2+
ARITHMETIC MEAN : https://en.wikipedia.org/wiki/Arithmetic_mean
3+
4+
"""
5+
6+
7+
def is_arithmetic_series(series: list) -> bool:
8+
"""
9+
checking whether the input series is arithmetic series or not
10+
11+
>>> is_arithmetic_series([2, 4, 6])
12+
True
13+
>>> is_arithmetic_series([3, 6, 12, 24])
14+
False
15+
>>> is_arithmetic_series([1, 2, 3])
16+
True
17+
"""
18+
if len(series) == 1:
19+
return True
20+
common_diff = series[1] - series[0]
21+
for index in range(len(series) - 1):
22+
if series[index + 1] - series[index] != common_diff:
23+
return False
24+
return True
25+
26+
27+
def arithmetic_mean(series: list) -> float:
28+
"""
29+
return the arithmetic mean of series
30+
31+
>>> arithmetic_mean([2, 4, 6])
32+
4.0
33+
>>> arithmetic_mean([3, 6, 9, 12])
34+
7.5
35+
>>> arithmetic_mean(4)
36+
Traceback (most recent call last):
37+
...
38+
ValueError: Input series is not valid, valid series - [2, 4, 6]
39+
>>> arithmetic_mean([4, 8, 1])
40+
Traceback (most recent call last):
41+
...
42+
ValueError: Input list is not an arithmetic series
43+
>>> arithmetic_mean([1, 2, 3])
44+
2.0
45+
>>> arithmetic_mean([])
46+
Traceback (most recent call last):
47+
...
48+
ValueError: Input list must be a non empty list
49+
50+
"""
51+
if not isinstance(series, list):
52+
raise ValueError("Input series is not valid, valid series - [2, 4, 6]")
53+
if len(series) == 0:
54+
raise ValueError("Input list must be a non empty list")
55+
if not is_arithmetic_series(series):
56+
raise ValueError("Input list is not an arithmetic series")
57+
answer = 0
58+
for val in series:
59+
answer += val
60+
return answer / len(series)
61+
62+
63+
if __name__ == "__main__":
64+
import doctest
65+
66+
doctest.testmod()

maths/series/geometric_mean.py

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
"""
2+
GEOMETRIC MEAN : https://en.wikipedia.org/wiki/Geometric_mean
3+
"""
4+
5+
6+
def is_geometric_series(series: list) -> bool:
7+
"""
8+
checking whether the input series is geometric series or not
9+
10+
>>> is_geometric_series([2, 4, 8])
11+
True
12+
>>> is_geometric_series([3, 6, 12, 24])
13+
True
14+
>>> is_geometric_series([1, 2, 3])
15+
False
16+
>>> is_geometric_series([0, 0, 3])
17+
False
18+
19+
"""
20+
if len(series) == 1:
21+
return True
22+
try:
23+
common_ratio = series[1] / series[0]
24+
for index in range(len(series) - 1):
25+
if series[index + 1] / series[index] != common_ratio:
26+
return False
27+
except ZeroDivisionError:
28+
return False
29+
return True
30+
31+
32+
def geometric_mean(series: list) -> float:
33+
"""
34+
return the geometric mean of series
35+
36+
>>> geometric_mean([2, 4, 8])
37+
3.9999999999999996
38+
>>> geometric_mean([3, 6, 12, 24])
39+
8.48528137423857
40+
>>> geometric_mean([4, 8, 16])
41+
7.999999999999999
42+
>>> geometric_mean(4)
43+
Traceback (most recent call last):
44+
...
45+
ValueError: Input series is not valid, valid series - [2, 4, 8]
46+
>>> geometric_mean([1, 2, 3])
47+
Traceback (most recent call last):
48+
...
49+
ValueError: Input list is not a geometric series
50+
>>> geometric_mean([0, 2, 3])
51+
Traceback (most recent call last):
52+
...
53+
ValueError: Input list is not a geometric series
54+
>>> geometric_mean([])
55+
Traceback (most recent call last):
56+
...
57+
ValueError: Input list must be a non empty list
58+
59+
"""
60+
if not isinstance(series, list):
61+
raise ValueError("Input series is not valid, valid series - [2, 4, 8]")
62+
if len(series) == 0:
63+
raise ValueError("Input list must be a non empty list")
64+
if not is_geometric_series(series):
65+
raise ValueError("Input list is not a geometric series")
66+
answer = 1
67+
for value in series:
68+
answer *= value
69+
return pow(answer, 1 / len(series))
70+
71+
72+
if __name__ == "__main__":
73+
import doctest
74+
75+
doctest.testmod()

other/graham_scan.py

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
"""
2+
This is a pure Python implementation of the merge-insertion sort algorithm
3+
Source: https://en.wikipedia.org/wiki/Graham_scan
4+
5+
For doctests run following command:
6+
python3 -m doctest -v graham_scan.py
7+
"""
8+
9+
from __future__ import annotations
10+
11+
from collections import deque
12+
from enum import Enum
13+
from math import atan2, degrees
14+
from sys import maxsize
15+
16+
17+
def graham_scan(points: list[list[int, int]]) -> list[list[int, int]]:
18+
"""Pure implementation of graham scan algorithm in Python
19+
20+
:param points: The unique points on coordinates.
21+
:return: The points on convex hell.
22+
23+
Examples:
24+
>>> graham_scan([(9, 6), (3, 1), (0, 0), (5, 5), (5, 2), (7, 0), (3, 3), (1, 4)])
25+
[(0, 0), (7, 0), (9, 6), (5, 5), (1, 4)]
26+
27+
>>> graham_scan([(0, 0), (1, 0), (1, 1), (0, 1)])
28+
[(0, 0), (1, 0), (1, 1), (0, 1)]
29+
30+
>>> graham_scan([(0, 0), (1, 1), (2, 2), (3, 3), (-1, 2)])
31+
[(0, 0), (1, 1), (2, 2), (3, 3), (-1, 2)]
32+
33+
>>> graham_scan([(-100, 20), (99, 3), (1, 10000001), (5133186, -25), (-66, -4)])
34+
[(5133186, -25), (1, 10000001), (-100, 20), (-66, -4)]
35+
"""
36+
37+
if len(points) <= 2:
38+
# There is no convex hull
39+
raise ValueError("graham_scan: argument must contain more than 3 points.")
40+
if len(points) == 3:
41+
return points
42+
# find the lowest and the most left point
43+
minidx = 0
44+
miny, minx = maxsize, maxsize
45+
for i, point in enumerate(points):
46+
x = point[0]
47+
y = point[1]
48+
if y < miny:
49+
miny = y
50+
minx = x
51+
minidx = i
52+
if y == miny:
53+
if x < minx:
54+
minx = x
55+
minidx = i
56+
57+
# remove the lowest and the most left point from points for preparing for sort
58+
points.pop(minidx)
59+
60+
def angle_comparer(point: list[int, int], minx: int, miny: int) -> float:
61+
"""Return the angle toward to point from (minx, miny)
62+
63+
:param point: The target point
64+
minx: The starting point's x
65+
miny: The starting point's y
66+
:return: the angle
67+
68+
Examples:
69+
>>> angle_comparer([1,1], 0, 0)
70+
45.0
71+
72+
>>> angle_comparer([100,1], 10, 10)
73+
-5.710593137499642
74+
75+
>>> angle_comparer([5,5], 2, 3)
76+
33.690067525979785
77+
"""
78+
# sort the points accorgind to the angle from the lowest and the most left point
79+
x = point[0]
80+
y = point[1]
81+
angle = degrees(atan2(y - miny, x - minx))
82+
return angle
83+
84+
sorted_points = sorted(points, key=lambda point: angle_comparer(point, minx, miny))
85+
# This insert actually costs complexity,
86+
# and you should insteadly add (minx, miny) into stack later.
87+
# I'm using insert just for easy understanding.
88+
sorted_points.insert(0, (minx, miny))
89+
90+
# traversal from the lowest and the most left point in anti-clockwise direction
91+
# if direction gets right, the previous point is not the convex hull.
92+
class Direction(Enum):
93+
left = 1
94+
straight = 2
95+
right = 3
96+
97+
def check_direction(
98+
starting: list[int, int], via: list[int, int], target: list[int, int]
99+
) -> Direction:
100+
"""Return the direction toward to the line from via to target from starting
101+
102+
:param starting: The starting point
103+
via: The via point
104+
target: The target point
105+
:return: the Direction
106+
107+
Examples:
108+
>>> check_direction([1,1], [2,2], [3,3])
109+
Direction.straight
110+
111+
>>> check_direction([60,1], [-50,199], [30,2])
112+
Direction.left
113+
114+
>>> check_direction([0,0], [5,5], [10,0])
115+
Direction.right
116+
"""
117+
x0, y0 = starting
118+
x1, y1 = via
119+
x2, y2 = target
120+
via_angle = degrees(atan2(y1 - y0, x1 - x0))
121+
if via_angle < 0:
122+
via_angle += 360
123+
target_angle = degrees(atan2(y2 - y0, x2 - x0))
124+
if target_angle < 0:
125+
target_angle += 360
126+
# t-
127+
# \ \
128+
# \ v
129+
# \|
130+
# s
131+
# via_angle is always lower than target_angle, if direction is left.
132+
# If they are same, it means they are on a same line of convex hull.
133+
if target_angle > via_angle:
134+
return Direction.left
135+
if target_angle == via_angle:
136+
return Direction.straight
137+
if target_angle < via_angle:
138+
return Direction.right
139+
140+
stack = deque()
141+
stack.append(sorted_points[0])
142+
stack.append(sorted_points[1])
143+
stack.append(sorted_points[2])
144+
# In any ways, the first 3 points line are towards left.
145+
# Because we sort them the angle from minx, miny.
146+
current_direction = Direction.left
147+
148+
for i in range(3, len(sorted_points)):
149+
while True:
150+
starting = stack[-2]
151+
via = stack[-1]
152+
target = sorted_points[i]
153+
next_direction = check_direction(starting, via, target)
154+
155+
if next_direction == Direction.left:
156+
current_direction = Direction.left
157+
break
158+
if next_direction == Direction.straight:
159+
if current_direction == Direction.left:
160+
# We keep current_direction as left.
161+
# Because if the straight line keeps as straight,
162+
# we want to know if this straight line is towards left.
163+
break
164+
elif current_direction == Direction.right:
165+
# If the straight line is towards right,
166+
# every previous points on those straigh line is not convex hull.
167+
stack.pop()
168+
if next_direction == Direction.right:
169+
stack.pop()
170+
stack.append(sorted_points[i])
171+
return list(stack)

project_euler/problem_109/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)