How to implement Modular Exponentiation Code - python

Please I was learning from the book Introduction to algorithm (Chapter 31 page 957) and came across this pseudocode. This pseudocode is how we can implement the modular-exponentiation. The pseudocode is as follows
MODULAR-EXPONENTIATION(a,b,n)
1 c = 0
2 d = 1
3 let <b_k,b_(k-i),....b_0> be the binary representation of b
4 for i = k downto 0
5 c = 2c
6 d = (d.d) mod n
7 if b_i == 1
8 c = c + 1
9 d = (d.a) mod n
10 return d
Then I tried to implement it in python
def modExpn(a,b,n):
c = 0
d = 1
binary_of_b = f'{b:b}'
len_of_b = len(binary_of_b)
for i in range(len_of_b,0,-1):
val = i - 1
c = 2 * c
d = (d * d) % n
if binary_of_b[val] == '1':
c = c + 1
d = (d * a) % n
return d
But when I tried running the function (modExpn) with a = 7,b=560 and n = 561 the output I had was 415 but the right answer is 1. Please where am I going wrong ?

You messed up while translating these parts from the pseudocode into actual code:
3 let <b_k,b_(k-i),....b_0> be the binary representation of b
4 for i = k **downto** 0
These instructions say that you should iterate from the left-most digit (b_k) of the binary representation to the right-most (b_0) since you need to go from k down to 0.
When you transform, for instance, 8 to binary you get "1000", and in Python the index of the left-most digit will be 0 and not len("1000") - 1 as you are doing.
In other words, if you just do:
for bin_digit in binary_of_b:
and later:
if bin_digit == '1':
your code is going to work.

Related

Python - How can I line up the equals sign of all my equations?

Currently in maths class we are working on gcd and I have written a Python script on my NumWorks calculator.
Here is the code I already wrote :
def div(n):
return [x for x in range(1,n+1) if n%x==0]
def pgcd(x,y):
a = x
b = y
while b > 0:
reste = a % b
print(a, "=", a//b, "*", b, "+", a%b)
a,b = b,reste
return "PGCD("+str(x)+";"+str(y)+") = " + str(a)
And it ouputs this :
pgcd(178,52)
178 = 3 * 52 + 22
52 = 2 * 22 + 8
22 = 2 * 8 + 6
8 = 1 * 6 + 2
6 = 3 * 2 + 0
I want it to output that :
178 = 3 * 52 + 22
52 = 2 * 22 + 8
22 = 2 * 8 + 6
8 = 1 * 6 + 2
6 = 3 * 2 + 0
I've read many articles online but I have no idea how to put that into my code.
Thanks in advance.
You can use the rjust string method.
The thing is you need to figure out what is the widest string on the left hand side you will print. Luckily here, it would be the first value.
So I would go with this.
def pgcd(x,y):
a = x
b = y
len_a = len(f"{a}")
while b > 0:
reste = a % b
print(f"{a}".rjust(len_a), "=", a//b, "*", b, "+", a%b)
a,b = b,reste
return "PGCD("+str(x)+";"+str(y)+") = " + str(a)
Should print this.
>>> pgcd(178,52)
178 = 3 * 52 + 22
52 = 2 * 22 + 8
22 = 2 * 8 + 6
8 = 1 * 6 + 2
6 = 3 * 2 + 0
'PGCD(178;52) = 2'
See .format for strings. An example of right justifying would look something like print('{:>6}'.format(42))
You can also use rjust
Use str.format() to achieve this:
'{0: >{width}}'.format(178, 3)
'{0: >{width}}'.format(52, 3)
Will output
178
52
Ok I asked it on a Discord server and they found out so if anyone is having the same problem as me here is the solution (did not put all code for space) :
def pgcd(x,y):
a = x
b = y
maxi = len(str(a))
while b > 0:
reste = a % b
print(" "*(maxi-len(str(a))),a, "=", a//b, "*", b, "+", a%b)
Basically compare to original code we added a maxi variable that has the maximum lenght of my integers, and then if the int is smaller like 8 compare to 178 we add to spaces because the difference of their length is 2.
This explanation is probably not 100% correct but it helps getting an idea.

Linearization of if-then constraint

I'm trying to linearize a constraint of this form:
if a == b then c = 1
where a and b are positive integers and c is a binary variable.
I'm looking for a solution like this one https://math.stackexchange.com/questions/2792360/how-to-linearize-if-then-constraint
which doesn't work in this case.
Thanks to anyone who can help me.
The implication
a = b => c = 1
(a,b: integer variables, c: a binary variable)
can be re-stated as:
c = 0 => a >= b + 1
or
a <= b - 1
(Using that a,b are integers). An "or" needs an extra binary variable. So we can write:
a >= b + 1 - M δ - M c
a <= b - 1 + M (1-δ) + M c
δ ∈ {0,1}
Here M is a large enough constant (to be chosen with care).

How can I make this more efficient? How can I measure my programs performance?

The question is to take an input = n, then take as many inputs as n and output, like this:
Which would mean this:
f(1,1) → 1
f(1,2) → 3
f(1,3) → 6
f(2,2) → 2
f(2,3) → 5
f(3,3) → 3
and
answer = 1 + 3 + 6 + 2 + 5 + 3 = 20 → ans = 1+3+6+2+5+3 = 20
What I came up with is this:
def f(l,r):
return int((r+l)*(r-l+1)/2)
n=int(input())
def WTF(n):
ans = 0
S=set()
for i in range(n):
S.add(int(input()))
for i2 in S:
for i3 in S:
if i3>=i2:
ans += f(i2,i3)
return ans
print(WTF(n))
But it was not accepted due to exceeding a time limit of 1 sec.
How can I make this run faster?

Karatsuba RecursionError: maximum recursion depth exceeded while calling a Python object

I am trying to implement Karatsuba multiplication on Python.
The inputs are two integers of length power of 2. They are of same length.
def mult(x,y):
if int(x) < 10 and int(y) <10:
return int(x)*int(y)
x_length = len(str(x))//2
y_length = len(str(y))//2
a = str(x)[:x_length]
b = str(x)[x_length:]
c = str(y)[:y_length]
d = str(y)[y_length:]
n = len(a) + len(b)
m = n//2
return 10**n* mult(a,c) + 10**m*(mult(a+b, c+d)-mult(a,c)-mult(b,d)) + mult(b,d)
Running
mult(1234,5678)
This gives the following error:
if int(x) < 10 and int(y) <10:
RecursionError: maximum recursion depth exceeded while calling a Python object
However if I do
def mult(x,y):
if int(x) < 10 and int(y) <10:
return int(x)*int(y)
x_length = len(str(x))//2
y_length = len(str(y))//2
a = str(x)[:x_length]
b = str(x)[x_length:]
c = str(y)[:y_length]
d = str(y)[y_length:]
n = len(a) + len(b)
m = n//2
return 10**n* mult(a,c) + 10**m*(mult(a,d)+mult(b,c)) + mult(b,d)
So I am doing 4 recursions in the last line (i.e. mult(a,c), mult(a,d), mult(b,c), mult(b,d)) rather than 3 as in the above (i.e. mult(a,c), mult(a+b, c+d), mult(b,d)).
Then it turns out ok.
Why is this happening? And how can I do it with only 3 recursions?
a, b, c, d are strings. String addition is concatenation. "1" + "2" is "12". So what is passed to mult(a+b, c+d) is not what you intended to pass.
TL;DR.
First thing first, the recursion is supposed to terminate quickly. Let's see why it doesn't. Add print x, y at the beginning of mult:
def mult(x, y):
print x, y
....
and redirect the output into a file. The result is surprising:
1234 5678
12 56
1 5
12 56
1 5
12 56
1 5
12 56
1 5
....
No wonder the stack overflows. Question is, why we repeat the 12 56 case? Let's add more instrumentation, to find out which recursive call does that:
def mult(x,y,k=-1):
....
print a, b, c, d
ac = mult(a, c, 0)
bd = mult(b, d, 2)
return 10**n* ac + 10**m*(mult(a+b, c+d, 1) - ac - bd) + bd
The results are
-1 : 1234 5678
12 34 56 78
0 : 12 56
1 2 5 6
0 : 1 5
2 : 2 6
1 : 12 56
1 2 5 6
0 : 1 5
2 : 2 6
1 : 12 56
1 2 5 6
0 : 1 5
2 : 2 6
1 : 12 56
You can see that the recursive call marked 1 always gets 12 56. It is the call which computes mult(a + b, c + d). Oh well. All of them a, b, c, d are strings. "1" + "2" is "12". Not exactly what you've meant.
So, make up your mind: are the parameters integer or strings, and treat them accordingly.
Note that in your first code snippet - you are calling your function not thrice, but 5 times:
return 10**n* mult(a,c) + 10**m*(mult(a+b, c+d)-mult(a,c)-mult(b,d)) + mult(b,d)
I can't really say for the rest of your code, but taking a quick look at the Wikipedia entry on Karatsuba, you can decrease your recursion depth by increasing the base number you are using (i.e. from 10 to 100 or 1000). You can change your recursion depth using sys.setrecursionlimit but python stack frames can get quite big, so try to avoid doing so as it may be dangerous.

Calculate the extended gcd using a recursive function in Python

I am given the function gcd, which is defined as follows:
def gcd(a, b):
if (0 == a % b):
return b
return gcd(b, a%b)
Now I am asked to write a recursive function gcd2(a,b) that returns a list of three numbers (g, s, t) where g = gcd(a, b) and g = s*a + t*b.
This means that you would enter two values (a and b) into the gcd(a, b) function. The value it returns equals g in the next function.
These same a and b values are then called into gcd2(a, b). The recursive part is then used to find the values for s and t so that g = s*a + t*b.
I am not sure how to approach this because I can't really envision what the "stopping-condition" would be, or what exactly I'd be looping through recursively to actually find s and t. Can anyone help me out?
The key insight is that we can work backwards, finding s and t for each a and b in the recursion. So say we have a = 21 and b = 15. We need to work through each iteration, using several values -- a, b, b % a, and c where a = c * b + a % b. First, let's consider each step of the basic GCD algorithm:
21 = 1 * 15 + 6
15 = 2 * 6 + 3
6 = 2 * 3 + 0 -> end recursion
So our gcd (g) is 3. Once we have that, we determine s and t for 6 and 3. To do so, we begin with g, expressing it in terms of (a, b, s, t = 3, 0, 1, -1):
3 = 1 * 3 + -1 * 0
Now we want to eliminate the 0 term. From the last line of the basic algorithm, we know that 0 = 6 - 2 * 3:
3 = 1 * 3 + -1 * (6 - 2 * 3)
Simplifying, we get
3 = 1 * 3 + -1 * 6 + 2 * 3
3 = 3 * 3 + -1 * 6
Now we swap the terms:
3 = -1 * 6 + 3 * 3
So we have s == -1 and t == 3 for a = 6 and b = 3. So given those values of a and b, gcd2 should return (3, -1, 3).
Now we step back up through the recursion, and we want to eliminate the 3 term. From the next-to-last line of the basic algorithm, we know that 3 = 15 - 2 * 6. Simplifying and swapping again (slowly, so that you can see the steps clearly...):
3 = -1 * 6 + 3 * (15 - 2 * 6)
3 = -1 * 6 + 3 * 15 - 6 * 6
3 = -7 * 6 + 3 * 15
3 = 3 * 15 + -7 * 6
So for this level of recursion, we return (3, 3, -7). Now we want to eliminate the 6 term.
3 = 3 * 15 + -7 * (21 - 1 * 15)
3 = 3 * 15 + 7 * 15 - 7 * 21
3 = 10 * 15 - 7 * 21
3 = -7 * 21 + 10 * 15
And voila, we have calculated s and t for 21 and 15.
So schematically, the recursive function will look like this:
def gcd2(a, b):
if (0 == a % b):
# calculate s and t
return b, s, t
else:
g, s, t = gcd2(b, a % b)
# calculate new_s and new_t
return g, new_s, new_t
Note that for our purposes here, using a slightly different base case simplifies things:
def gcd2(a, b):
if (0 == b):
return a, 1, -1
else:
g, s, t = gcd2(b, a % b)
# calculate new_s and new_t
return g, new_s, new_t
The base case (stopping condition) is:
if a%b == 0:
# a = b*k for the integer k=a/b
# rearranges to b = -1*a + (k+1)*b
# ( g = s*a + t*b )
return (b, -1, a/b+1) # (g, s, t)
However the exercise is to rewrite the recursive part:
g1, s1, t1 = gcd(b, a%b) # where g1 = s1*b + t1*(a%b)
g, s, t = ??? # where g = s*a + t*b
return (g, s, t)
in terms of g1, s1 and t1... which boils down to rewriting a%b in terms of a and b.
"Write a recursive function in Python", at least in CPython, cries for this: be aware of http://docs.python.org/library/sys.html#sys.getrecursionlimit. This is, in my opinion, one of the most important answers to this question. Please do some research on this topic yourself. Also, this thread might be insightful: Python: What is the hard recursion limit for Linux, Mac and Windows?
In conclusion, try to use an iterative instead of a recursive approach in Python whenever possible.
It is based on Euclidian algorithm using better to while loop continued recursion even better and less execution
def gcd(m,n):
#assume m>= n
if m <n:
(m,n) = (n,m)
if (m%n) == 0:
return(n)
else:
diff =m-n
#diff >n ?Possible!
return(gcd(max(n,diff),min(n,diff)))
it can be better by while loop
def gcd(m,n):
if m<n :
(m,n) =(n,m)
while (m%n) !=0:
diff =m-n
(m,n) =(max(n,diff),min(n,diff))
return(n)

Categories