GCD implementation in python - python

I am solving this problem in SPOJ and it states that :
Problem statement is simple. Given A and B you need to calculate
S(A,B) .
Here, f(n)=n, if n is square free otherwise 0. Also f(1)=1.
Input
The first line contains one integer T - denoting the number of test
cases.
T lines follow each containing two integers A,B.
Output
For each testcase output the value of S(A,B) mod 1000000007 in a
single line.
Constraints
`T <= 1000
1 <= A,B <= 1000000`
Example
Input:
3
42 18
35 1
20 25
Output:
306395
630
128819
I wrote this code for this problem (if I got the the problem right) :
def gcd(a,b): #gcd(a,b)
if b==0:
return a
else:
return gcd(b,a%b)
# print gcd(42,18)
import math
def issquarefree(n): #sqare free number check
i=2
s=i*i
if (n==1 or n==2) or n==3:
return True
while s<=n:
if n%s==0:
i=-1
break
else:
i+=1
s=i*i
if i==-1:return False
else:
return True
for i in range(int(raw_input())): #main program
a,b=map(int,raw_input().split())
g=gcd(a,b)
sa=(a*(a+1))/2 #see below
sb=(b*(b+1))/2 #see below
gc=issquarefree(g)
s=0
if gc== False:
print 0
elif gc==True:
s+=sa*sb*g
print s%1000000007
here I found that so applying this to the problem # S(A,B) I wrote this as (multiplication of sum of first A and B numbers ) multiplied by f(n) which is gcd(a,b) or 0.
But I am not getting the expected output to this problem so is my code wrong or I got the problem wrong
my output vs expected
3
35 1
42 18
20 25
630 630
926478 306395
341250 128819

Writing out the G(a, b) = f(gcd(a, b)) (so that you can use the cited formula) is incorrect since the function is not constant. The proper solution is this:
for i in range(int(raw_input())):
A, B = map(int, raw_input().split())
# proper algorithm
s = 0
for a in xrange(1, A):
for b in xrange(1, B):
s += a * b * G(a, b)
print s % 1000000007
You obviously have to implement G function properly (as returning 0 or gcd(a, b)).
Careful analysis of G might give some optimization insight but it is definitely not a trivial one if any.
Here is a simple optimization:
import fractions
DIVISOR = 1000000007
def is_not_square_free(a):
counter = 1
factor = 1
while factor < a:
counter += 1
factor = counter * counter
if a % factor == 0:
return True
return factor == a
def F(n):
if n == 1:
return 1
if is_not_square_free(n):
return 0
return n
_CACHE = {}
def G(a, b):
a = a % DIVISOR
b = b % DIVISOR
key = (a, b) if a > b else (b, a)
if key not in _CACHE:
_CACHE[key] = (a * b * F(fractions.gcd(a, b))) % DIVISOR
return _CACHE[key]
def S(A, B):
s = 0
for a in range(1, A+1):
for b in range(1, B+1):
s += G(a, b)
return s
for _ in range(int(raw_input())):
A, B = map(int, raw_input().split())
print(S(A, B) % DIVISOR)

def gcd(a, b):
returns greatest common divisor of a and b'''
return gcd(b % a, a) if a and b else max(a, b)
print test gcd should print 6,5, 7, and 9'''
print gcd(48,18)
print gcd(10,5)
print gcd(14,21)
print gcd (9,0)

Related

Variable not properly updating when searching for consecutive primes

Consider the following script:
Python
def f(a, b, n):
return (n ** 2) + (a * n) + b
def prime_check(num):
for i in range(2, (num // 2) + 1):
if num % i == 0:
return False
return True
num_primes = []
coefficients = []
for a in range(-999, 1000, 1):
for b in range(-1000, 1001, 1):
n = 0
coefficients.append((a, b))
while True:
result = prime_check(f(a, b, n))
if result:
n += 1
continue
else:
num_primes.append(n - 1)
break
print(f"num_primes: {num_primes[-1]} coefficients: {coefficients[-1]}")
The algorithm above is meant to search values of |a| < 1000 , |b| <= 1000, for function f(a, b, n), where n = 0 to start, and increments if f(a, b, n) returns a prime number. It keeps incrementing n and checking for primes until f returns a non-prime.
At this point, n - 1 is appended to num_primes to reflect the number of primes this set of coefficients (a, b) produced for consecutive values of n.
When I run this code, the print statement at the end of the inner for loop shows num_primes values are stuck alternating between whatever value b is for the current iteration and 0, rather than the proper number of primes for the coefficients.
I'm not sure where I went wrong here.
As noted by #JohanC, when prime_check(num) was given a negative number, it would return True no matter what the number was.
The fix for this was to make a simple change to prime_check(num) as shown below.
Python
def prime_check(num):
for i in range(2, (abs(num) // 2) + 1):
if num % i == 0:
return False
return True
By calculating abs(num) before division, we eliminate the bad behavior when num < 0.

Recursive function that returns the remainder

I am instructed to define a recursive function in Python that finds the remainder of n divided by b with the condition to not use the "/" ,"%" or "//" operator. I have defined the following function, which works fine for positive numbers. Is there a better way to do this using recursion and simple conditions.
def division(n, b, q = 1):
"""
parameters : a et b (integers)
returns: the remainder of a and b
pre-requisites : q = 1
"""
if n <= 0 or n < b:
if n == 0:
print("Your division has no remainder.")
elif n in range(0,5):
print("Your remainder is", n)
return 0
else:
return division(n - b, b, q) + q
print(division(274,5))
I believe your teacher was probably only trying to go for remainders without quotients.
def division(n, b):
if n < b:
return n
return division(n - b, b)
print(division(274, 5))
However, since you brought it up, you can do it with the quotient, without having to start with a 1 for the default.
def division(n, b, q = 0):
if n < b:
return n, q
return division(n - b, b, q + 1)
print(division(274, 5))
Main takeaways, you do not need to check n for range (0,5).
What about
def remainder(n, q):
if(n < q):
return n
return remainder(n - q, q)
print(remainder(274, 5)) # will return: 4
print(remainder(275, 5)) # will return: 0
print(remainder(123, 3)) # will return: 0
much shorter ...

Finding Greatest Common Divisor through iterative solution (python 3)

I am trying to find the great common divisor by using a function and solving it iteratively. Though, for some reason, I am not sure why I am not getting the right output.
The greatest common divisor between 30 & 15 should be 15, however, my output is always giving me the wrong number. I have a strong feeling that my "if" statement is strongly incorrect. Please help!
def square(a,b):
'''
x: int or float.
'''
c = a + b
while c > 0:
c -= 1
if a % c == 0 and b % c == 0:
return c
else:
return 1
obj = square(30,15)
print (obj)
You should return a value only if you finished iterating all numbers and found none of them a divisor to both numbers:
def square(a, b):
c = a + b
while c > 0:
if a % c == 0 and b % c == 0:
return c
c -= 1
return 1
However, the last return will be unneeded in this case, as c would go from a + b to 1, and mod 1 will always bring a common divisor, so the loop will always terminate with 1, for the worst case.
Also, a number greater than a and b can not be a common divisor of them. (x mod y for y > x yields x), and gcd is the formal name for the task, so I would go with
def gcd(a, b):
for c in range(min(a, b), 0, -1):
if a % c == b % c == 0:
return c
for iterational solution.
You might be interested to know that there is a common recursive solution to the GCD problem based on the Euclidian algorighm.
def gcd(a, b):
if b == 0:
return a
else:
return gcd(b, a % b)
print(gcd(30, 15))
# 15

Harmonic series in python

Does anyone know how to code the Harmonic Series in python?
H(n) = 1 + 1/2 + 1/3 + ... + 1/n
Note: We're not allowed to import from predefined modules. The output must be the numerator and the denominator of the answer in fraction form (lowest terms).
so here's my code for this harmonic series.
n = input("Enter n:")
def harmonic(n):
a=1
b=1
for d in range(2, n+1):
a = a*d+b
b = b*d
return (a,b)
x == max(a,b)%min(a, b)
if x == 0:
y=min(a,b)
return y
else:
y=min(a,b)/x
return y
a=a/y
b=b/y
return (a,b)
print harmonic(n)
what's wrong? Whatever I input, the output is always (3,2)
I have to check your attempt twice - and inserted a simple gcd (in the middle of the your original code)
n = input("Enter n:")
def harmonic(n): #original harmonic series
a=1
b=1
for d in range(2, n+1):
a = a*d+b
b = b*d
return(a,b)
def harmonic_lt(n): #_lt: harmonic series with lowest terms
#not pythonic, but simple
a=1
b=1
for d in range(2, n+1):
a = a*d+b
b = b*d
y=a
x=b
while x > 0:
re = y % x
y = x
x = re
a=a/y
b=b/y
return(a,b)
print harmonic(n)
print harmonic_lt(n)
As others pointed out, you are returning when d = 2 i.e. (1 + 1/2), it should be outside of the for loop.
Here's a code I wrote for doing the same:
#!Python2.7
def gcd(a, b):
if b: return gcd(b, a%b)
return a
def lcm(a, b):
return a*b/gcd(a, b)
def start():
n = int(raw_input())
ans = reduce(lambda x, y: (x[0]*lcm(x[1],y[1])/x[1]+y[0]*lcm(x[1],y[1])/y[1], lcm(x[1],y[1])),[(1,x) for x in xrange(1,n+1)])
_gcd = gcd(ans[0], ans[1])
print (ans[0]/_gcd, ans[1]/_gcd)
start()
If you want to avoid using reduce, lamda and list comprehensions:
#!Python2.7
def gcd(a, b):
if b: return gcd(b, a%b)
return a
def lcm(a, b):
assert a != 0
assert b != 0
return a*b/gcd(a, b)
def next(x, y):
lcmxy = lcm(x[1], y[1])
return (x[0]*lcmxy/x[1]+y[0]*lcmxy/y[1], lcmxy)
def start():
n = int(raw_input())
curr = (1,1)
for x in xrange(2,n+1):
curr = next(curr, (1,x))
_gcd = gcd(curr[0], curr[1])
print (curr[0]/_gcd, curr[1]/_gcd)
start()
You can find the denominator by finding the lowest common multiple of the numbers 1..n.
The nominator will then be the sum of all values denominator/x with x being all values from 1..n.
Here's some code:
def gcd(a, b):
"""Return greatest common divisor using Euclid's Algorithm."""
while b:
a, b = b, a % b
return a
def lcm(a, b):
"""Return lowest common multiple."""
return a * b // gcd(a, b)
def lcmm(args):
"""Return lcm of args."""
return reduce(lcm, args)
def harmonic(n):
lowest_common_multiple = lcmm(range(1,n))
nominator = sum([lowest_common_multiple/i for i in range(1,n)])
greatest_common_denominator = gcd(lowest_common_multiple, nominator)
return nominator/greatest_common_denominator, lowest_common_multiple/greatest_common_denominator
print harmonic(7)
print harmonic(10)
print harmonic(20)
Harmonic series:
1/1 + 1/2 + ... + 1/n == (n!/1 + n!/2 + ... + n!/n)/n!
therefore you can do:
nom = reduce(lambda s, x: s*x, xrange(1, n+1),1) # n!
denom = sum([nom / x for x in xrange(1, n+1)])
Then you need to do gcd-reduction on nom and denom.
Use the version from Thorsten Kranz.
Note that this way only one call to gcd is needed!
Example:
def gcd(a, b):
while b:
a, b = b, a % b
return a
def harmonic(n):
nom = reduce(lambda s, x: s*x, xrange(1,n+1), 1) # n!
denom = sum([nom / x for x in xrange(1, n+1)])
f = gcd(denom, nom)
return (denom / f), (nom / f)
print harmonic(10)
print harmonic(20)
(7381, 2520)
(55835135, 15519504)
You always return (a,b) at the first iteration. – Scharron"
Return always ends a function. If you return (a,b), the rest of the code is unreachable

Calculating logarithm, why is this algorithm not efficient, and how to make it more efficient?

I was wondering if I could calculate the logarithm of a number based on a number relative to a base (for example, log base 2 of 16) without actually using log(). I managed to do it, but I don't believe it is very efficient.
This is my code in Python:
def myLog(x,b):
exp=0
ans=b**exp
while x!=ans:
ans=b**exp
if ans==x:
return exp
exp=exp+1
So I could give it myLog(16,2) and it should return 4. And indeed it does, however I believe it is not the most efficient way, so how could I fix it and make my code more efficient, not just in this case, but in most of them?
Try recursion:
def func(a, b, ans=0):
if a/b == 1:
return ans + 1
else: return func(a/b, b, ans+1)
In [26]: func(16, 2)
Out[26]: 4
In [27]: func(8, 2)
Out[27]: 3
In [28]: func(16,4)
Out[28]: 2
Here's my two cents worth:
def myLog(x,b):
exp = 0
ans = 1
while ans<x:
ans *= b
exp += 1
if ans == x:
return exp
else:
raise ValueError("can't find a suitable exponent")
In [10]: myLog(16,2)
Out[10]: 4
Hope this helps
You're not taking into account if someone gives a negative value such as myLog(-1,2) or if it is 1 myLog(1,2), then you compute ans before the loop which you know it always be 0 because you put exp = 0, then in the loop you compute it again without before changing the exp.
logarithm python
Assumes:
x: a positive integer
b: a positive integer; b >= 2
returns: log_b(x), or, the logarithm of x relative to a base b.
Seems the shortest way is:
def myLog(x, b):
ans = 0
while b <= x:
ans += 1
x /= b
return ans
Or recursively:
def myLog(x, b):
if (b > x): return 0
else: return 1 + myLog(x/b, b)
Because it is an endless loop:
def myLog(x,b):
exp = 0
ans = b**exp
while x != ans:
ans = b**exp
if ans>x:
return -1
if ans == x:
return exp
exp = exp+1
See also:
What algorithm is used by computers to calculate logarithms?
Taylor series
This version adds support for non-integer outputs:
def log(a, b):
b = float(b)
a = float(a)
g = a
n = 0
i = 1
while b**i != 1:
while g >= b**i:
g /= b**i
n += i
i /= b
return n
def log(a, b):
b = float(b)
a = float(a)
g = a
n = 0
i = 1
while b**i != 1:
while g >= b**i:
g /= b**i
n += i
i /= b
return n
Does not work for all numbers. log(5,10) returns 0.00000 when it should be 0.69897

Categories

Resources