Skip to content

Commit 447e02d

Browse files
goswami-rahulHai Hoang Dang
authored and
Hai Hoang Dang
committed
added exponential and some refactors to maths/ (#361)
* added maths/modular_exponential.py and tests * cleared the requirements.txt * refactor math/factorial * refactor prime_check and sieve * added test_requirements.txt for travis
1 parent 6ad74b6 commit 447e02d

18 files changed

+155
-115
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ matrix:
1212
- python: 3.6
1313
env: TOX_ENV=py36
1414
install:
15-
- pip install -r requirements.txt
15+
- pip install -r test_requirements.txt
1616
before_script:
1717
# stop the build if there are Python syntax errors or undefined names
1818
- flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ If you want to uninstall algorithms, it is as simple as:
187187
- [gcd/lcm](algorithms/maths/gcd.py)
188188
- [generate_strobogrammtic](algorithms/maths/generate_strobogrammtic.py)
189189
- [is_strobogrammatic](algorithms/maths/is_strobogrammatic.py)
190+
- [modular_exponential](algorithms/maths/modular_exponential.py)
190191
- [next_bigger](algorithms/maths/next_bigger.py)
191192
- [next_perfect_square](algorithms/maths/next_perfect_square.py)
192193
- [nth_digit](algorithms/maths/nth_digit.py)

README_CN.md

+1
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ pip3 uninstall -y algorithms
183183
- [primes_sieve_of_eratosthenes:埃拉托色尼的质数筛](algorithms/maths/primes_sieve_of_eratosthenes.py)
184184
- [generate_strobogrammtic:生成对称数](algorithms/maths/generate_strobogrammtic.py)
185185
- [is_strobogrammatic:判断对称数](algorithms/maths/is_strobogrammatic.py)
186+
- [modular_exponential](algorithms/maths/modular_exponential.py)
186187
- [nth_digit:第n位](algorithms/maths/nth_digit.py)
187188
- [rabin_miller:米勒-拉宾素性检验](algorithms/maths/rabin_miller.py)
188189
- [rsa:rsa加密](algorithms/maths/rsa.py)

README_GE.md

+1
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ Um das Projekt zu deinstallieren tippen Sie folgendes:
193193
- [gcd/lcm](algorithms/maths/gcd.py)
194194
- [generate_strobogrammtic](algorithms/maths/generate_strobogrammtic.py)
195195
- [is_strobogrammatic](algorithms/maths/is_strobogrammatic.py)
196+
- [modular_exponential](algorithms/maths/modular_exponential.py)
196197
- [next_bigger](algorithms/maths/next_bigger.py)
197198
- [next_perfect_square](algorithms/maths/next_perfect_square.py)
198199
- [nth_digit](algorithms/maths/nth_digit.py)

README_JP.md

+1
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ if __name__ == "__main__":
187187
- [gcd/lcm](algorithms/maths/gcd.py)
188188
- [generate_strobogrammtic](algorithms/maths/generate_strobogrammtic.py)
189189
- [is_strobogrammatic](algorithms/maths/is_strobogrammatic.py)
190+
- [modular_exponential](algorithms/maths/modular_exponential.py)
190191
- [next_bigger](algorithms/maths/next_bigger.py)
191192
- [next_perfect_square](algorithms/maths/next_perfect_square.py)
192193
- [nth_digit](algorithms/maths/nth_digit.py)

README_KR.md

+1
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ if __name__ == "__main__":
184184
- [gcd/lcm](algorithms/maths/gcd.py)
185185
- [generate_strobogrammtic](algorithms/maths/generate_strobogrammtic.py)
186186
- [is_strobogrammatic](algorithms/maths/is_strobogrammatic.py)
187+
- [modular_exponential](algorithms/maths/modular_exponential.py)
187188
- [next_bigger](algorithms/maths/next_bigger.py)
188189
- [next_perfect_square](algorithms/maths/next_perfect_square.py)
189190
- [nth_digit](algorithms/maths/nth_digit.py)

algorithms/maths/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from .gcd import *
66
from .generate_strobogrammtic import *
77
from .is_strobogrammatic import *
8+
from .modular_exponential import *
89
from .next_perfect_square import *
910
from .prime_check import *
1011
from .primes_sieve_of_eratosthenes import *

algorithms/maths/extended_gcd.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
"""
2-
extended GCD algorithm
3-
return s,t,g
4-
such that a s + b t = GCD(a, b)
5-
and s and t are coprime
6-
"""
1+
def extended_gcd(a, b):
2+
"""Extended GCD algorithm.
3+
Return s, t, g
4+
such that a * s + b * t = GCD(a, b)
5+
and s and t are co-prime.
6+
"""
77

8-
def extended_gcd(a,b):
98
old_s, s = 1, 0
109
old_t, t = 0, 1
1110
old_r, r = a, b

algorithms/maths/factorial.py

+24-12
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,32 @@
1-
#
2-
# This function calculates n!
3-
# Factorial function not works in less than 0
4-
#
5-
6-
def factorial(n):
7-
1+
def factorial(n, mod=None):
2+
"""Calculates factorial iteratively.
3+
If mod is not None, then return (n! % mod)
4+
Time Complexity - O(n)"""
5+
if not (isinstance(n, int) and n >= 0):
6+
raise ValueError("'n' must be a non-negative integer.")
7+
if mod is not None and not (isinstance(mod, int) and mod > 0):
8+
raise ValueError("'mod' must be a positive integer")
89
result = 1
10+
if n == 0:
11+
return 1
912
for i in range(2, n+1):
1013
result *= i
11-
14+
if mod:
15+
result %= mod
1216
return result
1317

1418

15-
def factorial_recur(n):
19+
def factorial_recur(n, mod=None):
20+
"""Calculates factorial recursively.
21+
If mod is not None, then return (n! % mod)
22+
Time Complexity - O(n)"""
23+
if not (isinstance(n, int) and n >= 0):
24+
raise ValueError("'n' must be a non-negative integer.")
25+
if mod is not None and not (isinstance(mod, int) and mod > 0):
26+
raise ValueError("'mod' must be a positive integer")
1627
if n == 0:
1728
return 1
18-
19-
return n * factorial(n-1)
20-
29+
result = n * factorial(n - 1, mod)
30+
if mod:
31+
result %= mod
32+
return result
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
def modular_exponential(base, exponent, mod):
2+
"""Computes (base ^ exponent) % mod.
3+
Time complexity - O(log n)
4+
Use similar to Python in-built function pow."""
5+
if exponent < 0:
6+
raise ValueError("Exponent must be positive.")
7+
base %= mod
8+
result = 1
9+
10+
while exponent > 0:
11+
# If the last bit is 1, add 2^k.
12+
if exponent & 1:
13+
result = (result * base) % mod
14+
exponent = exponent >> 1
15+
# Utilize modular multiplication properties to combine the computed mod C values.
16+
base = (base * base) % mod
17+
18+
return result

algorithms/maths/nth_digit.py

+11-14
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
1-
"""
2-
find nth digit
3-
1. find the length of the number where the nth digit is from.
4-
2. find the actual number where the nth digit is from
5-
3. find the nth digit and return
6-
"""
7-
8-
91
def find_nth_digit(n):
10-
len = 1
2+
"""find the nth digit of given number.
3+
1. find the length of the number where the nth digit is from.
4+
2. find the actual number where the nth digit is from
5+
3. find the nth digit and return
6+
"""
7+
length = 1
118
count = 9
129
start = 1
13-
while n > len * count:
14-
n -= len * count
15-
len += 1
10+
while n > length * count:
11+
n -= length * count
12+
length += 1
1613
count *= 10
1714
start *= 10
18-
start += (n-1) / len
15+
start += (n-1) / length
1916
s = str(start)
20-
return int(s[(n-1) % len])
17+
return int(s[(n-1) % length])

algorithms/maths/prime_check.py

+4-23
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
"""
2-
prime_test(n) returns a True if n is a prime number else it returns False
3-
"""
4-
51
def prime_check(n):
2+
"""Return True if n is a prime number
3+
Else return False.
4+
"""
5+
66
if n <= 1:
77
return False
88
if n == 2 or n == 3:
@@ -15,22 +15,3 @@ def prime_check(n):
1515
return False
1616
j += 6
1717
return True
18-
19-
20-
def prime_check2(n):
21-
# prime numbers are greater than 1
22-
if n > 1:
23-
# check for factors
24-
for i in range(2, int(n ** 0.5) + 1):
25-
if (n % i) == 0:
26-
# print(num, "is not a prime number")
27-
# print(i, "times", num//i, "is", num)
28-
return False
29-
30-
# print(num, "is a prime number")
31-
return True
32-
33-
# if input number is less than
34-
# or equal to 1, it is not prime
35-
else:
36-
return False
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
'''
2-
Using sieve of Eratosthenes, primes(x) returns list of all primes less than x
1+
"""
2+
Return list of all primes less than n,
3+
Using sieve of Eratosthenes.
34
45
Modification:
56
We don't need to check all even numbers, we can make the sieve excluding even
67
numbers and adding 2 to the primes list by default.
78
8-
We are going to make an array of: x / 2 - 1 if number is even, else x / 2
9+
We are going to make an array of: x / 2 - 1 if number is even, else x / 2
910
(The -1 with even number it's to exclude the number itself)
1011
Because we just need numbers [from 3..x if x is odd]
1112
@@ -21,20 +22,25 @@
2122
2223
With this, we have reduced the array size to a half,
2324
and complexity it's also a half now.
24-
'''
25+
"""
2526

26-
def primes(x):
27-
assert(x >= 0)
27+
28+
def get_primes(n):
29+
"""Return list of all primes less than n,
30+
Using sieve of Eratosthenes.
31+
"""
32+
if n <= 0:
33+
raise ValueError("'n' must be a positive integer.")
2834
# If x is even, exclude x from list (-1):
29-
sieve_size = (x//2 - 1) if x % 2 == 0 else (x//2)
30-
sieve = [1 for v in range(sieve_size)] # Sieve
31-
primes = [] # List of Primes
32-
if x >= 2:
33-
primes.append(2) # Add 2 by default
35+
sieve_size = (n // 2 - 1) if n % 2 == 0 else (n // 2)
36+
sieve = [True for _ in range(sieve_size)] # Sieve
37+
primes = [] # List of Primes
38+
if n >= 2:
39+
primes.append(2) # 2 is prime by default
3440
for i in range(sieve_size):
35-
if sieve[i] == 1:
41+
if sieve[i]:
3642
value_at_i = i*2 + 3
3743
primes.append(value_at_i)
3844
for j in range(i, sieve_size, value_at_i):
39-
sieve[j] = 0
45+
sieve[j] = False
4046
return primes

algorithms/maths/rsa.py

+8-9
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,20 @@
2424
import random
2525

2626

27-
def modinv(a, m):
28-
"""calculate the inverse of a mod m
29-
that is, find b such that (a * b) % m == 1"""
30-
b = 1
31-
while not (a * b) % m == 1:
32-
b += 1
33-
return b
34-
35-
3627
def generate_key(k, seed=None):
3728
"""
3829
the RSA key generating algorithm
3930
k is the number of bits in n
4031
"""
4132

33+
def modinv(a, m):
34+
"""calculate the inverse of a mod m
35+
that is, find b such that (a * b) % m == 1"""
36+
b = 1
37+
while not (a * b) % m == 1:
38+
b += 1
39+
return b
40+
4241
def gen_prime(k, seed=None):
4342
"""generate a prime with k bits"""
4443

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
"""
22
Given a positive integer N and a precision factor P,
3-
write a square root function that produce an output
3+
it produces an output
44
with a maximum error P from the actual square root of N.
55
66
Example:
7-
Given N = 5 and P = 0.001, can produce output O such that
8-
2.235 < O > 2.237. Actual square root of 5 being 2.236.
7+
Given N = 5 and P = 0.001, can produce output x such that
8+
2.235 < x < 2.237. Actual square root of 5 being 2.236.
99
"""
1010

11-
def square_root(n,p):
12-
guess = float(n) / 2
1311

14-
while abs(guess * guess - n) > p:
15-
guess = (guess + (n / guess)) / 2
12+
def square_root(n, epsilon=0.001):
13+
"""Return square root of n, with maximum absolute error epsilon"""
14+
guess = n / 2
1615

17-
return guess
16+
while abs(guess * guess - n) > epsilon:
17+
guess = (guess + (n / guess)) / 2
18+
19+
return guess

requirements.txt

-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +0,0 @@
1-
flake8
2-
python-coveralls
3-
coverage
4-
nose
5-
pytest
6-
tox

test_requirements.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
flake8
2+
python-coveralls
3+
coverage
4+
nose
5+
pytest
6+
tox

0 commit comments

Comments
 (0)