Unable to crack Python code for GCD of 3 numbers? - python

I am trying to find the GCD of 3 numbers but have been unable to get around much success till now. I am using the following code
def gcd(a, b,c):
if sum(np.array(list([a,b,c]))%min(a,b,c))==0:
return min(a,b,c)
else:
x = np.array(list([a,b,c]))%min(a,b,c)
if sum((list([x]))%min(x))==0:
return min(x)
When I run this on an example say gcd(21,45,60), it gives me the below error
C:\Users\mmt8091\Anaconda3\lib\site-packages\ipykernel_launcher.py:6: RuntimeWarning: divide by zero encountered in remainder
What am i doing wrong here? Have been unable to find any other solutions on net as well. Please help

You do not need np.
Try this:
def gcd(*args):
a, b, *c = args
a, b = min(a, b), max(a, b)
gcd1 = b if not a else gcd(b % a, a)
for i in c:
gcd1 = gcd(gcd1, i)
return gcd1
print(gcd(21, 45, 60))

Related

RSA Python Issue

I am having an issue with getting my python program to decrypt a message with an RSA problem. For some reason my Python program is stalling, really just not outputting anything. Anyone got an idea as to why?
n = 23952937352643527451379227516428377705004894508566304313177880191662177061878993798938496818120987817049538365206671401938265663712351239785237507341311858383628932183083145614696585411921662992078376103990806989257289472590902167457302888198293135333083734504191910953238278860923153746261500759411620299864395158783509535039259714359526738924736952759753503357614939203434092075676169179112452620687731670534906069845965633455748606649062394293289967059348143206600765820021392608270528856238306849191113241355842396325210132358046616312901337987464473799040762271876389031455051640937681745409057246190498795697239
p = 153143042272527868798412612417204434156935146874282990942386694020462861918068684561281763577034706600608387699148071015194725533394126069826857182428660427818277378724977554365910231524827258160904493774748749088477328204812171935987088715261127321911849092207070653272176072509933245978935455542420691737433
c = 18031488536864379496089550017272599246134435121343229164236671388038630752847645738968455413067773166115234039247540029174331743781203512108626594601293283737392240326020888417252388602914051828980913478927759934805755030493894728974208520271926698905550119698686762813722190657005740866343113838228101687566611695952746931293926696289378849403873881699852860519784750763227733530168282209363348322874740823803639617797763626570478847423136936562441423318948695084910283653593619962163665200322516949205854709192890808315604698217238383629613355109164122397545332736734824591444665706810731112586202816816647839648399
e = 65537
q = 156408916769576372285319235535320446340733908943564048157238512311891352879208957302116527435165097143521156600690562005797819820759620198602417583539668686152735534648541252847927334505648478214810780526425005943955838623325525300844493280040860604499838598837599791480284496210333200247148213274376422459183
phi = (q-1)*(p-1)
d = pow(e,-1,phi)
m = pow(c,d)%n
print(m)
I apologize for the weird code formatting. Thanks in advance.
Assuming the math is correct (I didn't check), you definitely want to change this:
m = pow(c,d)%n
to this:
m = pow(c, d, n)
The first spelling computes c**d to full precision before dividing by n to find the remainder. That can be enormously expensive. The second way keeps reducing intermediate results, under the covers, mod n all along, and never needs to do arithmetic in integers larger than about n**2.
So, replacing the last line of your code and continuing:
>>> m = pow(c, d, n) # less than an eyeblink
>>> m
14311663942709674867122208214901970650496788151239520971623411712977120586163535880168563325
>>> pow(m, e, n) == c
True
So the original "message" (c) is recovered by doing modular exponentiation to powers d and e in turn.
As already answered by #TimPeters main issue you have is pow(c,d)%n which should be replaced with pow(c, d, n) for huge performance improvement.
So as your question was already answered, I decided to dig a bit further. Inspired by your question I decided to implement most of RSA mathematics from scratch according to WikiPedia article. Maybe it is a bit offtopic (not what you asked) but I'm sure next code will be useful demo for somebody who wants to try RSA in plain Python, and may be helpful to you too.
Next code has all variables named same as in wikipedia, formulas are also taken from there. Important!, one thing is missing in my code, I didn't implement padding for simplicity (just to show classical RSA math), it is very important to have correct (e.g. OAEP) padding in your system, without it there exist attacks on RSA. Also I used just 512 bits for prime parts of modulus, real systems shoud have thousands of bits to be secure. Also I don't do any splitting of message, long messages should be split into sub-messages and padded to fit modulus bitsize.
Try it online!
import random
def fermat_prp(n):
# https://en.wikipedia.org/wiki/Fermat_primality_test
assert n >= 4, n
for i in range(24):
a = (3, 5, 7)[i] if n >= 9 and i < 3 else random.randint(2, n - 2)
if pow(a, n - 1, n) != 1:
return False
return True
def gen_prime(bits):
assert bits >= 3, bits
while True:
n = random.randrange(1 << (bits - 1), 1 << bits)
if fermat_prp(n):
return n
def gcd(a, b):
while b != 0:
a, b = b, a % b
return a
def lcm(a, b):
return a * b // gcd(a, b)
def egcd(a, b):
# https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
ro, r, so, s, to, t = a, b, 1, 0, 0, 1
while r != 0:
q = ro // r
ro, r = r, ro - q * r
so, s = s, so - q * s
to, t = t, to - q * t
return ro, so, to
def demo():
# https://en.wikipedia.org/wiki/RSA_(cryptosystem)
bits = 512
p, q = gen_prime(bits), gen_prime(bits)
n = p * q
ln = lcm(p - 1, q - 1)
e = 65537
print('PublicKey: e =', e, 'n =', n)
d = egcd(e, ln)[1] % ln
mtext = 'Hello, World!'
print('Plain:', mtext)
m = int.from_bytes(mtext.encode('utf-8'), 'little')
c = pow(m, e, n)
print('Encrypted:', c)
md = pow(c, d, n)
mdtext = md.to_bytes((md.bit_length() + 7) // 8, 'little').decode('utf-8')
print('Decrypted:', mdtext)
if __name__ == '__main__':
demo()
Output:
PublicKey: e = 65537 n = 110799663895649286762656294752173883884148615506062673584673343016070245791505883867301519267702723384430131035038547340921850290913097297607190494504060280758901448419479350528305305851775098631904614278162314251019568026506239421634950337278112960925116975344093575400871044570868887447462560168862887909233
Plain: Hello, World!
Encrypted: 51626387443589883457155394323971044262931599278626885275220384098221412582734630381413609428210758734789774315702921245355044370166117558802434906927834933002999816979504781510321118769252529439999715937013823223670924340787833496790181098038607416880371509879507193070745708801500713956266209367343820073123
Decrypted: Hello, World!

Evaluate Derivative of Function at a Point Python 2.7

I have the following function:
import sympy as sp
def inverted(q, m, a, nu):
return (-1)**(m+1)*(a/m)**m*sp.exp(m)*q**(-nu)*sp.diff(1/(sp.sqrt(a**2+q**2))*(sp.sqrt(a**2+q**2)-a)**(nu), a, m+1)
I want to define some lambda function such that
f100 = lambda a, q: inverted(q, 100, a, 0)
However, when I try to examine
q = sp.symbols('q')
f100(1000.0, q)
I get the following output:
ValueError:
Can't calculate 101st derivative wrt 10.
Obviously, what is happening is when I call f100(1000.0, q), the function refers back to inverted and the issue arises. I was hoping for a way around this.
Seems like you have to make a a variable first so diff works. It doesn't work if you fix a before (I think because you differentiate with respect to a). You can substitute a with 1000 afterwards.
import sympy as sp
def inverted(q, m, a, nu):
return (-1)**(m+1)*(a/m)**m*sp.exp(m)*q**(-nu)*sp.diff(1/(sp.sqrt(a**2+q**2))*(sp.sqrt(a**2+q**2)-a)**(nu), a, m+1)
f100 = lambda a, q: inverted(q, 100, a, 0)
q, a = sp.symbols('q, a')
print(f100(a, q).subs(a, 1000))

Median of three, pivot

I'm looking for the median of three, using this for a pivot in a QuickSort. I would not like to import any statistics library because I believe it creates a bit of overhead which I would like to reduce as much as possible.
def median(num_list):
if (num_list[0] > num_list[len(num_list) - 1]) and (num_list[0] < num_list[int(len(num_list)//2)]):
return num_list[0]
elif (num_list[int(len(num_list)//2)] > num_list[len(num_list) - 1]) and (num_list[0] > num_list[int(len(num_list)//2)]):
return num_list[int(len(num_list)//2)]
else:
return num_list[len(num_list) - 1]
this seems to be returning the last else statement every time, I'm stumped...
In Quicksort you do not usually want just to know the median of three, you want to arrange the three values so the smallest is in one spot, the median in another, and the maximum in yet another. But if you really just want the median of three, here are two ways, plus another that rearranges.
Here's a short way to find the median of a, b, and c.
return a + b + c - min(a, b, c) - max(a, b, c)
If you want only comparisons, and to get what may be the quickest code, realize that three comparisons may need to be executed but you want to try for only two. (Two comparisons can handle four cases, but there are six arrangements of three objects.) Try
if a < b:
if b < c:
return b
elif a < c:
return c
else:
return a
else:
if a < c:
return a
elif b < c:
return c
else:
return b
If you want to rearrange the values so a <= b <= c,
if a > b:
a, b = b, a
if b > c:
b, c = c, b
if a > b
a, b = b, a
return b
Let Python do the work for you. Sort the three elements, then return the middle one.
def median(num_list):
return sorted([num_list[0], num_list[len(num_list) // 2], num_list[-1]])[1]
Using min and max:
>>> numlist = [21, 12, 16]
>>> a, b, c = numlist
>>> max(min(a,b), min(b,c), min(a,c))
16
>>>
Going out on a limb - I have a functional streak so here is the itertools equivalent, even though it means importing a module
>>> import itertools
>>> numlist = [21, 12, 16]
>>> z = itertools.combinations(numlist, 2)
>>> y = itertools.imap(min, z)
>>> max(y)
16

finding the LCM using python

def multiple(a, b):
"""so I'm trying to return the smallest number n that is a multiple of both a and b.
for example:
multiple(3, 4)
12
multiple(14, 21)
42
"""
def gcd (a,b):
if a < b : a , b = b,a
while b:
a , b = b , a % b
return a
def lcm (a , b):
n= (a*b) / gcd(a,b)
return n
it keeps throwing errors about indentation and logic. I don't understand why. I've tried changing the variables around too.
No need to find GCD, we can directly find LCM. Below code works
def lcmof(x,y):
res=0
mx=max(x,y)
mn=min(x,y)
for i in range(1,mx+1,1):
temp=mx*i
try:
if(temp%mn==0):
res=temp
break
except ZeroDivisionError:
res=0
break
return res

Difficulty in implementing Strassen's algorithm in Python

I don't understand how to call my code recursively. Here is my code so far:
import numpy
B = [[5,5,5,5,5,5,5,5],[6,6,6,6,6,6,6,6],[7,7,7,7,7,7,7,7],[8,8,8,8,8,8,8,8],
[9,9,9,9,9,9,9,9], [10,10,10,10,10,10,10,10],[11,11,11,11,11,11,11,11], [12,12,12,12,12,12,12,12]]
A = [[5,5,5,5,5,5,5,5],[6,6,6,6,6,6,6,6],[7,7,7,7,7,7,7,7],[8,8,8,8,8,8,8,8],
[1,1,1,1,1,1,1,1], [2,2,2,2,2,2,2,2],[3,3,3,3,3,3,3,3],[4,4,4,4,4,4,4,4]]
def main():
strassen(A,B)
def strassen(A, B):
A = numpy.asarray(A)
B = numpy.asarray(B)
lengthA = len(A)
lengthB = len(B)
if lengthA == 2:
print "will calculate"
else:
a, b = strassen(A[:lengthA//2, :lengthA//2], B[:lengthB//2, :lengthB//2])
lengthA = lengthA//2
lengthB = lengthB//2
print a
print b
return a, b
I'm trying to reduce a to [[5,5],[6,6]] and b to [[5,5],[6,6]] but I'm getting an error:
a, b = strassen(A[:lengthA//2, :lengthA//2], B[:lengthB//2, :lengthB//2])
TypeError: 'NoneType' object is not iterable.
a and b are the 1st 2x2 matrices that will be formed after the 2nd whole matrix division for A and B. Please can someone explain this to me. Thanks
You have no return value in your recursion terminating condition. When I run your code, it prints "will calculate" before giving the error. The error happens after that because there is no return value from the strassen function on the last call (when lengthA == 2).

Categories

Resources