move-files-and-2-renames (#4285)

This commit is contained in:
algobytewise
2021-03-22 15:22:26 +05:30
committed by GitHub
parent 14bcb580d5
commit 8d51c2cfd9
11 changed files with 134 additions and 134 deletions

View File

@ -0,0 +1,50 @@
"""
* Binary Exponentiation with Multiplication
* This is a method to find a*b in a time complexity of O(log b)
* This is one of the most commonly used methods of finding result of multiplication.
* Also useful in cases where solution to (a*b)%c is required,
* where a,b,c can be numbers over the computers calculation limits.
* Done using iteration, can also be done using recursion
* @author chinmoy159
* @version 1.0 dated 10/08/2017
"""
def b_expo(a, b):
res = 0
while b > 0:
if b & 1:
res += a
a += a
b >>= 1
return res
def b_expo_mod(a, b, c):
res = 0
while b > 0:
if b & 1:
res = ((res % c) + (a % c)) % c
a += a
b >>= 1
return res
"""
* Wondering how this method works !
* It's pretty simple.
* Let's say you need to calculate a ^ b
* RULE 1 : a * b = (a+a) * (b/2) ---- example : 4 * 4 = (4+4) * (4/2) = 8 * 2
* RULE 2 : IF b is ODD, then ---- a * b = a + (a * (b - 1)) :: where (b - 1) is even.
* Once b is even, repeat the process to get a * b
* Repeat the process till b = 1 OR b = 0, because a*1 = a AND a*0 = 0
*
* As far as the modulo is concerned,
* the fact : (a+b) % c = ((a%c) + (b%c)) % c
* Now apply RULE 1 OR 2, whichever is required.
"""

View File

@ -0,0 +1,50 @@
"""
* Binary Exponentiation for Powers
* This is a method to find a^b in a time complexity of O(log b)
* This is one of the most commonly used methods of finding powers.
* Also useful in cases where solution to (a^b)%c is required,
* where a,b,c can be numbers over the computers calculation limits.
* Done using iteration, can also be done using recursion
* @author chinmoy159
* @version 1.0 dated 10/08/2017
"""
def b_expo(a, b):
res = 1
while b > 0:
if b & 1:
res *= a
a *= a
b >>= 1
return res
def b_expo_mod(a, b, c):
res = 1
while b > 0:
if b & 1:
res = ((res % c) * (a % c)) % c
a *= a
b >>= 1
return res
"""
* Wondering how this method works !
* It's pretty simple.
* Let's say you need to calculate a ^ b
* RULE 1 : a ^ b = (a*a) ^ (b/2) ---- example : 4 ^ 4 = (4*4) ^ (4/2) = 16 ^ 2
* RULE 2 : IF b is ODD, then ---- a ^ b = a * (a ^ (b - 1)) :: where (b - 1) is even.
* Once b is even, repeat the process to get a ^ b
* Repeat the process till b = 1 OR b = 0, because a^1 = a AND a^0 = 1
*
* As far as the modulo is concerned,
* the fact : (a*b) % c = ((a%c) * (b%c)) % c
* Now apply RULE 1 OR 2 whichever is required.
"""

47
maths/euclidean_gcd.py Normal file
View File

@ -0,0 +1,47 @@
""" https://en.wikipedia.org/wiki/Euclidean_algorithm """
def euclidean_gcd(a: int, b: int) -> int:
"""
Examples:
>>> euclidean_gcd(3, 5)
1
>>> euclidean_gcd(6, 3)
3
"""
while b:
a, b = b, a % b
return a
def euclidean_gcd_recursive(a: int, b: int) -> int:
"""
Recursive method for euclicedan gcd algorithm
Examples:
>>> euclidean_gcd_recursive(3, 5)
1
>>> euclidean_gcd_recursive(6, 3)
3
"""
return a if b == 0 else euclidean_gcd_recursive(b, a % b)
def main():
print(f"euclidean_gcd(3, 5) = {euclidean_gcd(3, 5)}")
print(f"euclidean_gcd(5, 3) = {euclidean_gcd(5, 3)}")
print(f"euclidean_gcd(1, 3) = {euclidean_gcd(1, 3)}")
print(f"euclidean_gcd(3, 6) = {euclidean_gcd(3, 6)}")
print(f"euclidean_gcd(6, 3) = {euclidean_gcd(6, 3)}")
print(f"euclidean_gcd_recursive(3, 5) = {euclidean_gcd_recursive(3, 5)}")
print(f"euclidean_gcd_recursive(5, 3) = {euclidean_gcd_recursive(5, 3)}")
print(f"euclidean_gcd_recursive(1, 3) = {euclidean_gcd_recursive(1, 3)}")
print(f"euclidean_gcd_recursive(3, 6) = {euclidean_gcd_recursive(3, 6)}")
print(f"euclidean_gcd_recursive(6, 3) = {euclidean_gcd_recursive(6, 3)}")
if __name__ == "__main__":
main()

View File

@ -0,0 +1,126 @@
"""
Author : Syed Faizan ( 3rd Year IIIT Pune )
Github : faizan2700
Purpose : You have one function f(x) which takes float integer and returns
float you have to integrate the function in limits a to b.
The approximation proposed by Thomas Simpsons in 1743 is one way to calculate
integration.
( read article : https://cp-algorithms.com/num_methods/simpson-integration.html )
simpson_integration() takes function,lower_limit=a,upper_limit=b,precision and
returns the integration of function in given limit.
"""
# constants
# the more the number of steps the more accurate
N_STEPS = 1000
def f(x: float) -> float:
return x * x
"""
Summary of Simpson Approximation :
By simpsons integration :
1. integration of fxdx with limit a to b is =
f(x0) + 4 * f(x1) + 2 * f(x2) + 4 * f(x3) + 2 * f(x4)..... + f(xn)
where x0 = a
xi = a + i * h
xn = b
"""
def simpson_integration(function, a: float, b: float, precision: int = 4) -> float:
"""
Args:
function : the function which's integration is desired
a : the lower limit of integration
b : upper limit of integraion
precision : precision of the result,error required default is 4
Returns:
result : the value of the approximated integration of function in range a to b
Raises:
AssertionError: function is not callable
AssertionError: a is not float or integer
AssertionError: function should return float or integer
AssertionError: b is not float or integer
AssertionError: precision is not positive integer
>>> simpson_integration(lambda x : x*x,1,2,3)
2.333
>>> simpson_integration(lambda x : x*x,'wrong_input',2,3)
Traceback (most recent call last):
...
AssertionError: a should be float or integer your input : wrong_input
>>> simpson_integration(lambda x : x*x,1,'wrong_input',3)
Traceback (most recent call last):
...
AssertionError: b should be float or integer your input : wrong_input
>>> simpson_integration(lambda x : x*x,1,2,'wrong_input')
Traceback (most recent call last):
...
AssertionError: precision should be positive integer your input : wrong_input
>>> simpson_integration('wrong_input',2,3,4)
Traceback (most recent call last):
...
AssertionError: the function(object) passed should be callable your input : ...
>>> simpson_integration(lambda x : x*x,3.45,3.2,1)
-2.8
>>> simpson_integration(lambda x : x*x,3.45,3.2,0)
Traceback (most recent call last):
...
AssertionError: precision should be positive integer your input : 0
>>> simpson_integration(lambda x : x*x,3.45,3.2,-1)
Traceback (most recent call last):
...
AssertionError: precision should be positive integer your input : -1
"""
assert callable(
function
), f"the function(object) passed should be callable your input : {function}"
assert isinstance(a, float) or isinstance(
a, int
), f"a should be float or integer your input : {a}"
assert isinstance(function(a), float) or isinstance(function(a), int), (
"the function should return integer or float return type of your function, "
f"{type(a)}"
)
assert isinstance(b, float) or isinstance(
b, int
), f"b should be float or integer your input : {b}"
assert (
isinstance(precision, int) and precision > 0
), f"precision should be positive integer your input : {precision}"
# just applying the formula of simpson for approximate integraion written in
# mentioned article in first comment of this file and above this function
h = (b - a) / N_STEPS
result = function(a) + function(b)
for i in range(1, N_STEPS):
a1 = a + h * i
result += function(a1) * (4 if i % 2 else 2)
result *= h / 3
return round(result, precision)
if __name__ == "__main__":
import doctest
doctest.testmod()

View File

@ -0,0 +1,23 @@
from sys import maxsize
def max_sub_array_sum(a: list, size: int = 0):
"""
>>> max_sub_array_sum([-13, -3, -25, -20, -3, -16, -23, -12, -5, -22, -15, -4, -7])
-3
"""
size = size or len(a)
max_so_far = -maxsize - 1
max_ending_here = 0
for i in range(0, size):
max_ending_here = max_ending_here + a[i]
if max_so_far < max_ending_here:
max_so_far = max_ending_here
if max_ending_here < 0:
max_ending_here = 0
return max_so_far
if __name__ == "__main__":
a = [-13, -3, -25, -20, 1, -16, -23, -12, -5, -22, -15, -4, -7]
print(("Maximum contiguous sum is", max_sub_array_sum(a, len(a))))

View File

@ -0,0 +1,45 @@
"""
Given an array of integer elements and an integer 'k', we are required to find the
maximum sum of 'k' consecutive elements in the array.
Instead of using a nested for loop, in a Brute force approach we will use a technique
called 'Window sliding technique' where the nested loops can be converted to a single
loop to reduce time complexity.
"""
from typing import List
def max_sum_in_array(array: List[int], k: int) -> int:
"""
Returns the maximum sum of k consecutive elements
>>> arr = [1, 4, 2, 10, 2, 3, 1, 0, 20]
>>> k = 4
>>> max_sum_in_array(arr, k)
24
>>> k = 10
>>> max_sum_in_array(arr,k)
Traceback (most recent call last):
...
ValueError: Invalid Input
>>> arr = [1, 4, 2, 10, 2, 13, 1, 0, 2]
>>> k = 4
>>> max_sum_in_array(arr, k)
27
"""
if len(array) < k or k < 0:
raise ValueError("Invalid Input")
max_sum = current_sum = sum(array[:k])
for i in range(len(array) - k):
current_sum = current_sum - array[i] + array[i + k]
max_sum = max(max_sum, current_sum)
return max_sum
if __name__ == "__main__":
from doctest import testmod
from random import randint
testmod()
array = [randint(-1000, 1000) for i in range(100)]
k = randint(0, 110)
print(f"The maximum sum of {k} consecutive elements is {max_sum_in_array(array,k)}")

View File

@ -0,0 +1,33 @@
from typing import List
def median_of_two_arrays(nums1: List[float], nums2: List[float]) -> float:
"""
>>> median_of_two_arrays([1, 2], [3])
2
>>> median_of_two_arrays([0, -1.1], [2.5, 1])
0.5
>>> median_of_two_arrays([], [2.5, 1])
1.75
>>> median_of_two_arrays([], [0])
0
>>> median_of_two_arrays([], [])
Traceback (most recent call last):
...
IndexError: list index out of range
"""
all_numbers = sorted(nums1 + nums2)
div, mod = divmod(len(all_numbers), 2)
if mod == 1:
return all_numbers[div]
else:
return (all_numbers[div] + all_numbers[div - 1]) / 2
if __name__ == "__main__":
import doctest
doctest.testmod()
array_1 = [float(x) for x in input("Enter the elements of first array: ").split()]
array_2 = [float(x) for x in input("Enter the elements of second array: ").split()]
print(f"The median of two arrays is: {median_of_two_arrays(array_1, array_2)}")

644
maths/primelib.py Normal file
View File

@ -0,0 +1,644 @@
"""
Created on Thu Oct 5 16:44:23 2017
@author: Christian Bender
This Python library contains some useful functions to deal with
prime numbers and whole numbers.
Overview:
isPrime(number)
sieveEr(N)
getPrimeNumbers(N)
primeFactorization(number)
greatestPrimeFactor(number)
smallestPrimeFactor(number)
getPrime(n)
getPrimesBetween(pNumber1, pNumber2)
----
isEven(number)
isOdd(number)
gcd(number1, number2) // greatest common divisor
kgV(number1, number2) // least common multiple
getDivisors(number) // all divisors of 'number' inclusive 1, number
isPerfectNumber(number)
NEW-FUNCTIONS
simplifyFraction(numerator, denominator)
factorial (n) // n!
fib (n) // calculate the n-th fibonacci term.
-----
goldbach(number) // Goldbach's assumption
"""
from math import sqrt
def isPrime(number):
"""
input: positive integer 'number'
returns true if 'number' is prime otherwise false.
"""
# precondition
assert isinstance(number, int) and (
number >= 0
), "'number' must been an int and positive"
status = True
# 0 and 1 are none primes.
if number <= 1:
status = False
for divisor in range(2, int(round(sqrt(number))) + 1):
# if 'number' divisible by 'divisor' then sets 'status'
# of false and break up the loop.
if number % divisor == 0:
status = False
break
# precondition
assert isinstance(status, bool), "'status' must been from type bool"
return status
# ------------------------------------------
def sieveEr(N):
"""
input: positive integer 'N' > 2
returns a list of prime numbers from 2 up to N.
This function implements the algorithm called
sieve of erathostenes.
"""
# precondition
assert isinstance(N, int) and (N > 2), "'N' must been an int and > 2"
# beginList: contains all natural numbers from 2 up to N
beginList = [x for x in range(2, N + 1)]
ans = [] # this list will be returns.
# actual sieve of erathostenes
for i in range(len(beginList)):
for j in range(i + 1, len(beginList)):
if (beginList[i] != 0) and (beginList[j] % beginList[i] == 0):
beginList[j] = 0
# filters actual prime numbers.
ans = [x for x in beginList if x != 0]
# precondition
assert isinstance(ans, list), "'ans' must been from type list"
return ans
# --------------------------------
def getPrimeNumbers(N):
"""
input: positive integer 'N' > 2
returns a list of prime numbers from 2 up to N (inclusive)
This function is more efficient as function 'sieveEr(...)'
"""
# precondition
assert isinstance(N, int) and (N > 2), "'N' must been an int and > 2"
ans = []
# iterates over all numbers between 2 up to N+1
# if a number is prime then appends to list 'ans'
for number in range(2, N + 1):
if isPrime(number):
ans.append(number)
# precondition
assert isinstance(ans, list), "'ans' must been from type list"
return ans
# -----------------------------------------
def primeFactorization(number):
"""
input: positive integer 'number'
returns a list of the prime number factors of 'number'
"""
# precondition
assert isinstance(number, int) and number >= 0, "'number' must been an int and >= 0"
ans = [] # this list will be returns of the function.
# potential prime number factors.
factor = 2
quotient = number
if number == 0 or number == 1:
ans.append(number)
# if 'number' not prime then builds the prime factorization of 'number'
elif not isPrime(number):
while quotient != 1:
if isPrime(factor) and (quotient % factor == 0):
ans.append(factor)
quotient /= factor
else:
factor += 1
else:
ans.append(number)
# precondition
assert isinstance(ans, list), "'ans' must been from type list"
return ans
# -----------------------------------------
def greatestPrimeFactor(number):
"""
input: positive integer 'number' >= 0
returns the greatest prime number factor of 'number'
"""
# precondition
assert isinstance(number, int) and (
number >= 0
), "'number' bust been an int and >= 0"
ans = 0
# prime factorization of 'number'
primeFactors = primeFactorization(number)
ans = max(primeFactors)
# precondition
assert isinstance(ans, int), "'ans' must been from type int"
return ans
# ----------------------------------------------
def smallestPrimeFactor(number):
"""
input: integer 'number' >= 0
returns the smallest prime number factor of 'number'
"""
# precondition
assert isinstance(number, int) and (
number >= 0
), "'number' bust been an int and >= 0"
ans = 0
# prime factorization of 'number'
primeFactors = primeFactorization(number)
ans = min(primeFactors)
# precondition
assert isinstance(ans, int), "'ans' must been from type int"
return ans
# ----------------------
def isEven(number):
"""
input: integer 'number'
returns true if 'number' is even, otherwise false.
"""
# precondition
assert isinstance(number, int), "'number' must been an int"
assert isinstance(number % 2 == 0, bool), "compare bust been from type bool"
return number % 2 == 0
# ------------------------
def isOdd(number):
"""
input: integer 'number'
returns true if 'number' is odd, otherwise false.
"""
# precondition
assert isinstance(number, int), "'number' must been an int"
assert isinstance(number % 2 != 0, bool), "compare bust been from type bool"
return number % 2 != 0
# ------------------------
def goldbach(number):
"""
Goldbach's assumption
input: a even positive integer 'number' > 2
returns a list of two prime numbers whose sum is equal to 'number'
"""
# precondition
assert (
isinstance(number, int) and (number > 2) and isEven(number)
), "'number' must been an int, even and > 2"
ans = [] # this list will returned
# creates a list of prime numbers between 2 up to 'number'
primeNumbers = getPrimeNumbers(number)
lenPN = len(primeNumbers)
# run variable for while-loops.
i = 0
j = None
# exit variable. for break up the loops
loop = True
while i < lenPN and loop:
j = i + 1
while j < lenPN and loop:
if primeNumbers[i] + primeNumbers[j] == number:
loop = False
ans.append(primeNumbers[i])
ans.append(primeNumbers[j])
j += 1
i += 1
# precondition
assert (
isinstance(ans, list)
and (len(ans) == 2)
and (ans[0] + ans[1] == number)
and isPrime(ans[0])
and isPrime(ans[1])
), "'ans' must contains two primes. And sum of elements must been eq 'number'"
return ans
# ----------------------------------------------
def gcd(number1, number2):
"""
Greatest common divisor
input: two positive integer 'number1' and 'number2'
returns the greatest common divisor of 'number1' and 'number2'
"""
# precondition
assert (
isinstance(number1, int)
and isinstance(number2, int)
and (number1 >= 0)
and (number2 >= 0)
), "'number1' and 'number2' must been positive integer."
rest = 0
while number2 != 0:
rest = number1 % number2
number1 = number2
number2 = rest
# precondition
assert isinstance(number1, int) and (
number1 >= 0
), "'number' must been from type int and positive"
return number1
# ----------------------------------------------------
def kgV(number1, number2):
"""
Least common multiple
input: two positive integer 'number1' and 'number2'
returns the least common multiple of 'number1' and 'number2'
"""
# precondition
assert (
isinstance(number1, int)
and isinstance(number2, int)
and (number1 >= 1)
and (number2 >= 1)
), "'number1' and 'number2' must been positive integer."
ans = 1 # actual answer that will be return.
# for kgV (x,1)
if number1 > 1 and number2 > 1:
# builds the prime factorization of 'number1' and 'number2'
primeFac1 = primeFactorization(number1)
primeFac2 = primeFactorization(number2)
elif number1 == 1 or number2 == 1:
primeFac1 = []
primeFac2 = []
ans = max(number1, number2)
count1 = 0
count2 = 0
done = [] # captured numbers int both 'primeFac1' and 'primeFac2'
# iterates through primeFac1
for n in primeFac1:
if n not in done:
if n in primeFac2:
count1 = primeFac1.count(n)
count2 = primeFac2.count(n)
for i in range(max(count1, count2)):
ans *= n
else:
count1 = primeFac1.count(n)
for i in range(count1):
ans *= n
done.append(n)
# iterates through primeFac2
for n in primeFac2:
if n not in done:
count2 = primeFac2.count(n)
for i in range(count2):
ans *= n
done.append(n)
# precondition
assert isinstance(ans, int) and (
ans >= 0
), "'ans' must been from type int and positive"
return ans
# ----------------------------------
def getPrime(n):
"""
Gets the n-th prime number.
input: positive integer 'n' >= 0
returns the n-th prime number, beginning at index 0
"""
# precondition
assert isinstance(n, int) and (n >= 0), "'number' must been a positive int"
index = 0
ans = 2 # this variable holds the answer
while index < n:
index += 1
ans += 1 # counts to the next number
# if ans not prime then
# runs to the next prime number.
while not isPrime(ans):
ans += 1
# precondition
assert isinstance(ans, int) and isPrime(
ans
), "'ans' must been a prime number and from type int"
return ans
# ---------------------------------------------------
def getPrimesBetween(pNumber1, pNumber2):
"""
input: prime numbers 'pNumber1' and 'pNumber2'
pNumber1 < pNumber2
returns a list of all prime numbers between 'pNumber1' (exclusive)
and 'pNumber2' (exclusive)
"""
# precondition
assert (
isPrime(pNumber1) and isPrime(pNumber2) and (pNumber1 < pNumber2)
), "The arguments must been prime numbers and 'pNumber1' < 'pNumber2'"
number = pNumber1 + 1 # jump to the next number
ans = [] # this list will be returns.
# if number is not prime then
# fetch the next prime number.
while not isPrime(number):
number += 1
while number < pNumber2:
ans.append(number)
number += 1
# fetch the next prime number.
while not isPrime(number):
number += 1
# precondition
assert (
isinstance(ans, list) and ans[0] != pNumber1 and ans[len(ans) - 1] != pNumber2
), "'ans' must been a list without the arguments"
# 'ans' contains not 'pNumber1' and 'pNumber2' !
return ans
# ----------------------------------------------------
def getDivisors(n):
"""
input: positive integer 'n' >= 1
returns all divisors of n (inclusive 1 and 'n')
"""
# precondition
assert isinstance(n, int) and (n >= 1), "'n' must been int and >= 1"
ans = [] # will be returned.
for divisor in range(1, n + 1):
if n % divisor == 0:
ans.append(divisor)
# precondition
assert ans[0] == 1 and ans[len(ans) - 1] == n, "Error in function getDivisiors(...)"
return ans
# ----------------------------------------------------
def isPerfectNumber(number):
"""
input: positive integer 'number' > 1
returns true if 'number' is a perfect number otherwise false.
"""
# precondition
assert isinstance(number, int) and (
number > 1
), "'number' must been an int and >= 1"
divisors = getDivisors(number)
# precondition
assert (
isinstance(divisors, list)
and (divisors[0] == 1)
and (divisors[len(divisors) - 1] == number)
), "Error in help-function getDivisiors(...)"
# summed all divisors up to 'number' (exclusive), hence [:-1]
return sum(divisors[:-1]) == number
# ------------------------------------------------------------
def simplifyFraction(numerator, denominator):
"""
input: two integer 'numerator' and 'denominator'
assumes: 'denominator' != 0
returns: a tuple with simplify numerator and denominator.
"""
# precondition
assert (
isinstance(numerator, int)
and isinstance(denominator, int)
and (denominator != 0)
), "The arguments must been from type int and 'denominator' != 0"
# build the greatest common divisor of numerator and denominator.
gcdOfFraction = gcd(abs(numerator), abs(denominator))
# precondition
assert (
isinstance(gcdOfFraction, int)
and (numerator % gcdOfFraction == 0)
and (denominator % gcdOfFraction == 0)
), "Error in function gcd(...,...)"
return (numerator // gcdOfFraction, denominator // gcdOfFraction)
# -----------------------------------------------------------------
def factorial(n):
"""
input: positive integer 'n'
returns the factorial of 'n' (n!)
"""
# precondition
assert isinstance(n, int) and (n >= 0), "'n' must been a int and >= 0"
ans = 1 # this will be return.
for factor in range(1, n + 1):
ans *= factor
return ans
# -------------------------------------------------------------------
def fib(n):
"""
input: positive integer 'n'
returns the n-th fibonacci term , indexing by 0
"""
# precondition
assert isinstance(n, int) and (n >= 0), "'n' must been an int and >= 0"
tmp = 0
fib1 = 1
ans = 1 # this will be return
for i in range(n - 1):
tmp = ans
ans += fib1
fib1 = tmp
return ans

89
maths/triplet_sum.py Normal file
View File

@ -0,0 +1,89 @@
"""
Given an array of integers and another integer target,
we are required to find a triplet from the array such that it's sum is equal to
the target.
"""
from __future__ import annotations
from itertools import permutations
from random import randint
from timeit import repeat
def make_dataset() -> tuple[list[int], int]:
arr = [randint(-1000, 1000) for i in range(10)]
r = randint(-5000, 5000)
return (arr, r)
dataset = make_dataset()
def triplet_sum1(arr: list[int], target: int) -> tuple[int, int, int]:
"""
Returns a triplet in the array with sum equal to target,
else (0, 0, 0).
>>> triplet_sum1([13, 29, 7, 23, 5], 35)
(5, 7, 23)
>>> triplet_sum1([37, 9, 19, 50, 44], 65)
(9, 19, 37)
>>> arr = [6, 47, 27, 1, 15]
>>> target = 11
>>> triplet_sum1(arr, target)
(0, 0, 0)
"""
for triplet in permutations(arr, 3):
if sum(triplet) == target:
return tuple(sorted(triplet))
return (0, 0, 0)
def triplet_sum2(arr: list[int], target: int) -> tuple[int, int, int]:
"""
Returns a triplet in the array with sum equal to target,
else (0, 0, 0).
>>> triplet_sum2([13, 29, 7, 23, 5], 35)
(5, 7, 23)
>>> triplet_sum2([37, 9, 19, 50, 44], 65)
(9, 19, 37)
>>> arr = [6, 47, 27, 1, 15]
>>> target = 11
>>> triplet_sum2(arr, target)
(0, 0, 0)
"""
arr.sort()
n = len(arr)
for i in range(n - 1):
left, right = i + 1, n - 1
while left < right:
if arr[i] + arr[left] + arr[right] == target:
return (arr[i], arr[left], arr[right])
elif arr[i] + arr[left] + arr[right] < target:
left += 1
elif arr[i] + arr[left] + arr[right] > target:
right -= 1
return (0, 0, 0)
def solution_times() -> tuple[float, float]:
setup_code = """
from __main__ import dataset, triplet_sum1, triplet_sum2
"""
test_code1 = """
triplet_sum1(*dataset)
"""
test_code2 = """
triplet_sum2(*dataset)
"""
times1 = repeat(setup=setup_code, stmt=test_code1, repeat=5, number=10000)
times2 = repeat(setup=setup_code, stmt=test_code2, repeat=5, number=10000)
return (min(times1), min(times2))
if __name__ == "__main__":
from doctest import testmod
testmod()
times = solution_times()
print(f"The time for naive implementation is {times[0]}.")
print(f"The time for optimized implementation is {times[1]}.")

61
maths/two_pointer.py Normal file
View File

@ -0,0 +1,61 @@
"""
Given a sorted array of integers, return indices of the two numbers such
that they add up to a specific target using the two pointers technique.
You may assume that each input would have exactly one solution, and you
may not use the same element twice.
This is an alternative solution of the two-sum problem, which uses a
map to solve the problem. Hence can not solve the issue if there is a
constraint not use the same index twice. [1]
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
[1]: https://github.com/TheAlgorithms/Python/blob/master/other/two_sum.py
"""
from __future__ import annotations
def two_pointer(nums: list[int], target: int) -> list[int]:
"""
>>> two_pointer([2, 7, 11, 15], 9)
[0, 1]
>>> two_pointer([2, 7, 11, 15], 17)
[0, 3]
>>> two_pointer([2, 7, 11, 15], 18)
[1, 2]
>>> two_pointer([2, 7, 11, 15], 26)
[2, 3]
>>> two_pointer([1, 3, 3], 6)
[1, 2]
>>> two_pointer([2, 7, 11, 15], 8)
[]
>>> two_pointer([3 * i for i in range(10)], 19)
[]
>>> two_pointer([1, 2, 3], 6)
[]
"""
i = 0
j = len(nums) - 1
while i < j:
if nums[i] + nums[j] == target:
return [i, j]
elif nums[i] + nums[j] < target:
i = i + 1
else:
j = j - 1
return []
if __name__ == "__main__":
import doctest
doctest.testmod()
print(f"{two_pointer([2, 7, 11, 15], 9) = }")

47
maths/two_sum.py Normal file
View File

@ -0,0 +1,47 @@
"""
Given an array of integers, return indices of the two numbers such that they add up to
a specific target.
You may assume that each input would have exactly one solution, and you may not use the
same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
"""
from __future__ import annotations
def two_sum(nums: list[int], target: int) -> list[int]:
"""
>>> two_sum([2, 7, 11, 15], 9)
[0, 1]
>>> two_sum([15, 2, 11, 7], 13)
[1, 2]
>>> two_sum([2, 7, 11, 15], 17)
[0, 3]
>>> two_sum([7, 15, 11, 2], 18)
[0, 2]
>>> two_sum([2, 7, 11, 15], 26)
[2, 3]
>>> two_sum([2, 7, 11, 15], 8)
[]
>>> two_sum([3 * i for i in range(10)], 19)
[]
"""
chk_map = {}
for index, val in enumerate(nums):
compl = target - val
if compl in chk_map:
return [chk_map[compl], index]
chk_map[val] = index
return []
if __name__ == "__main__":
import doctest
doctest.testmod()
print(f"{two_sum([2, 7, 11, 15], 9) = }")