Your task is to given two integer numbers, a and b calculate the modular multiplicative inverse of a modulo b, if it exists.
The modular inverse of a modulo b is a number c such that ac ≡ 1 (mod b). This number is unique modulo b for any pair of a and b. It exists only if the greatest common divisor of a and b is 1.
The Wikipedia page for modular multiplicative inverse can be consulted if you require more information about the topic.
Input and Output
Input is given as either two integers or a list of two integers. Your program should output either a single number, the modular multiplicative inverse that is in the interval 0 < c < b, or a value indicating there is no inverse. The value can be anything, except a number in the range (0,b), and may also be an exception. The value should however be the same for cases in which there is no inverse.
0 < a < b can be assumed
Rules
- The program should finish at some point, and should solve each test case in less than 60 seconds
- Standard loopholes apply
Test cases
Test cases below are given in the format, a, b -> output
1, 2 -> 1
3, 6 -> Does not exist
7, 87 -> 25
25, 87 -> 7
2, 91 -> 46
13, 91 -> Does not exist
19, 1212393831 -> 701912218
31, 73714876143 -> 45180085378
3, 73714876143 -> Does not exist
Scoring
This is code golf, so the shortest code for each language wins.
This and this are similar questions, but both ask for specific situations.
-
7\$\begingroup\$ It follows from Fermat's Little Theorem that the multiplicative inverse of a, if it exists, can be computed efficiently as a^(phi(b)-1) mod b, where phi is Euler's totient function: phi(p0^k0 * p1^k1 * ...) = (p0-1) * p0^(k0-1) * (p1-1) * p1^(k1-1) * ... Not saying it leads to shorter code :) \$\endgroup\$ngn– ngn2017年08月24日 16:08:29 +00:00Commented Aug 24, 2017 at 16:08
-
1\$\begingroup\$ @Jenny_mathy Taking additional input is generally disallowed. \$\endgroup\$Mr. Xcoder– Mr. Xcoder2017年08月24日 16:32:49 +00:00Commented Aug 24, 2017 at 16:32
-
5\$\begingroup\$ I count six answers that seem to be brute forcing, and unlikely to run all test cases in 60 seconds (some of them give a stack or memory error first). \$\endgroup\$Ørjan Johansen– Ørjan Johansen2017年08月24日 23:28:40 +00:00Commented Aug 24, 2017 at 23:28
-
1\$\begingroup\$ @ngn : You've conflated Fermat's Little Theorem (FLT) with Euler's improvement to it. Fermat did not know about the Euler phi function. Further, FLT and Euler's improvement only apply if gcd(a,b) = 1. Finally, in the form you have written it, "a^(\phi(b)-1) mod b" is congruent to 1, not a^(-1). To get a^(-1), use a^(\phi(b)-2) mod b. \$\endgroup\$Eric Towers– Eric Towers2017年08月25日 04:49:59 +00:00Commented Aug 25, 2017 at 4:49
-
1\$\begingroup\$ @EricTowers Euler's is a consequence. Regarding "gcd(a,b)=1" - I did say "if it [the inverse] exists". Are you sure about phi(b)-2? \$\endgroup\$ngn– ngn2017年08月25日 06:45:29 +00:00Commented Aug 25, 2017 at 6:45
27 Answers 27
Mathematica, 14 bytes
Obligatory Mathematica builtin:
ModularInverse
It's a function that takes two arguments (a and b), and returns the inverse of a mod b if it exists. If not, it returns the error ModularInverse: a is not invertible modulo b..
JavaScript (ES6), (削除) 79 (削除ここまで) (削除) 73 (削除ここまで) (削除) 62 (削除ここまで) 61 bytes
Returns false if the inverse does not exist.
It uses the extended Euclidean algorithm and solves all test cases almost instantly.
f=(a,b,c=!(n=b),d=1)=>a?f(b%a,a,d,c-(b-b%a)/a*d):b<2&&(c+n)%n
Test cases
f=(a,b,c=!(n=b),d=1)=>a?f(b%a,a,d,c-(b-b%a)/a*d):b<2&&(c+n)%n
console.log(f(1, 2)) // -> 1
console.log(f(3, 6)) // -> Does not exist
console.log(f(7, 87)) // -> 25
console.log(f(25, 87)) // -> 7
console.log(f(2, 91)) // -> 46
console.log(f(13, 91)) // -> Does not exist
console.log(f(19, 1212393831)) // -> 701912218
console.log(f(31, 73714876143)) // -> 45180085378
console.log(f(3, 73714876143)) // -> Does not exist
-
\$\begingroup\$ Why is it not possible to write the name of function f, as in f(c,a,b=0,d=1,n=a)=>c?f(a%c,c,d,b-(a-a%c)/c*d,n):a<2&&(b+n)%n ? \$\endgroup\$user58988– user589882017年08月24日 17:47:06 +00:00Commented Aug 24, 2017 at 17:47
-
\$\begingroup\$ @RosLup
f(x,y)is always parsed as a function call, except if it is explicitly preceded by thefunctionkeyword. An anonymous arrow function, on the other hand, is declared as(x,y)=>somethingandf=(x,y)=>somethingassigns the function to thefvariable. \$\endgroup\$Arnauld– Arnauld2017年08月24日 18:01:11 +00:00Commented Aug 24, 2017 at 18:01
Python 2, 34 bytes
f=lambda a,b:a==1or-~b*f(-b%a,a)/a
Recursive function that gives True for print f(1,2), which I believe to be acceptable, and errors for invalid inputs.
We are trying to find \$x\$ in \$a\cdot x\equiv 1\pmod{b}\$.
This can be written as \$a\cdot x-1=k\cdot b\$ where \$k\$ is an integer.
Taking \$\mod{a}\$ of this gives \$-1\equiv k\cdot b\pmod{a}\$. Moving the minus gives \$-k\cdot b\equiv1\pmod{a}\$, where we have to solve for \$k\$.
Seeing how it resembles the initial scenario, allow us to recurse to solve for \$k\$ by calling the function with \$f(-b\%a,a)\$ (works because Python gives positive values for modulo with a negative argument).
The program recurses for until \$a\$ becomes 1, which only happens if the original \$a\$ and \$b\$ are coprime to each other (ie there exists a multiplicative inverse), or ends in an error caused by division by 0.
This value of \$k\$ can be substituted in the equation \$a\cdot x-1=k\cdot b\$ to give \$x\$ as \$\frac{k\cdot b+1}{a}\$.
Jelly, 2 bytes
æi
This uses a builtin for modular inverse, and returns 0 for no modular inverse.
Jelly, 7 bytes
×ばつ%8’¬T
Outputs empty set (represented as empty string) on no modular inverse. Runs out of memory on TIO for the largest test-cases, but should work given enough memory.
How it Works
×ばつ%8’¬T
R Generate range of b
×ばつ Multiply each by a
%8 Mod each by b
’ Decrement (Map 1 to 0 and all else to truthy)
¬ Logical NOT
T Get the index of the truthy element.
If you want to work for larger test-cases, try this (relatively ungolfed) version, which requires much time rather than memory:
Jelly, 9 bytes
×ばつ4%3’¬ø1#
How it Works
×ばつ4%3’¬ø1#
# Get the first
ø1 one integer
which meets×ばつ4 When multiplied by a
%3 And modulo-d by b
’ Decrement
¬ Is falsy
Mathematica, 18 bytes
PowerMod[#,-1,#2]&
input
[31, 73714876143]
R + numbers, 15 bytes
numbers::modinv
returns NA for those a without inverses mod b.
R, 33 bytes (non-competing)
This will fail on very large b since it actually creates a vector of size 32*b bits.
function(a,b)which((1:b*a)%%b==1)
Returns integer(0) (an empty list) for those a without inverses mod b.
Japt, (削除) 9 (削除ここまで) 8 bytes
Takes the inputs in reverse order. Outputs -1 for no match. Craps out as the bigger integer gets larger.
Ç*V%UÃb1
- Saved 1 byte thanks to ETH pointing out an errant, and very obvious, space.
-
\$\begingroup\$ The test input
73714876143,31seems to produce an out-of-memory error on Firefox (and to crash Chromium). I don't think this is a valid answer. \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年08月25日 00:54:47 +00:00Commented Aug 25, 2017 at 0:54 -
\$\begingroup\$ @IlmariKaronen: I clearly pointed out that fact in my solution. We can assume infinite memory for the purposes of code golf so the memory issues and crashes do not invalidate this solution. \$\endgroup\$Shaggy– Shaggy2017年08月25日 08:51:55 +00:00Commented Aug 25, 2017 at 8:51
-
3\$\begingroup\$ Unfortunately the memory issues also make it impossible to tell whether your code would actually solve the test cases in 60 seconds as stipulated by the challenge. I suspect it would not, even if there was sufficient memory available to make it not crash, but without a computer that can actually run the program for that long there's no way to tell for sure. \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年08月25日 10:09:09 +00:00Commented Aug 25, 2017 at 10:09
Python 3 + gmpy, 23 bytes
I don't think it can get any shorter in Python.
gmpy.invert
import gmpy
Try it online! (won't work if you do not have gmpy installed)
Python 3, 49 bytes
lambda a,b:[c for c in range(b)if-~c*a%b==1][0]+1
Python 3, 50 bytes
lambda a,b:[c for c in range(1,b+1)if c*a%b==1][0]
This throws IndexError: list index out of range in case there is no modular multiplicative inverse, as it is allowed by the rules.
-
\$\begingroup\$ This fails to return a result for the input
31,73714876143in 60 seconds (on TIO). \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年08月25日 00:58:07 +00:00Commented Aug 25, 2017 at 0:58 -
\$\begingroup\$ @IlmariKaronen Seems to finish in 56 seconds on my machine (Macbook Pro '15) \$\endgroup\$Mr. Xcoder– Mr. Xcoder2017年08月25日 04:58:15 +00:00Commented Aug 25, 2017 at 4:58
Python 2, (削除) 51 (削除ここまで) (削除) 49 (削除ここまで) (削除) 54 (削除ここまで) (削除) 53 (削除ここまで) (削除) 51 (削除ここまで) 49 bytes
-1 byte thanks to officialaimm
-1 byte thanks to Shaggy
a,b=input()
i=a<2
while(a*i%b-1)*b%a:i+=1
print+i
Prints 0 when there is no solution.
-
1\$\begingroup\$ Outputs
0fora=1andb=2; from the test cases, it should output1. \$\endgroup\$Shaggy– Shaggy2017年08月24日 16:03:36 +00:00Commented Aug 24, 2017 at 16:03 -
\$\begingroup\$ As a recursive algo \$\endgroup\$Mr. Xcoder– Mr. Xcoder2017年08月24日 16:03:43 +00:00Commented Aug 24, 2017 at 16:03
-
1\$\begingroup\$ As Shaggy pointed out, fails for
2, 1\$\endgroup\$Mr. Xcoder– Mr. Xcoder2017年08月24日 16:06:10 +00:00Commented Aug 24, 2017 at 16:06 -
1\$\begingroup\$ This fails to return an answer in 60 seconds (on TIO) for the input
31,73714876143. \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年08月25日 00:49:37 +00:00Commented Aug 25, 2017 at 0:49 -
1\$\begingroup\$ This goes into infinite loop for the input
4, 6, since there is no inverse, butb%a != 0. (For inverse to exist, it's not enough thatbis not divisible bya, you need them to be coprime.) \$\endgroup\$Arthur– Arthur2017年08月25日 07:41:38 +00:00Commented Aug 25, 2017 at 7:41
8th, 6 bytes
Code
invmod
Explanation
invmod is a 8th word that calculates the value of the inverse of a, modulo b. It returns null on overflow or other errors.
Usage and test cases
ok> 1 2 invmod .
1
ok> 3 6 invmod .
null
ok> 7 87 invmod .
25
ok> 25 87 invmod .
7
ok> 2 91 invmod .
46
ok> 13 91 invmod .
null
ok> 19 1212393831 invmod .
701912218
ok> 31 73714876143 invmod .
45180085378
ok> 3 73714876143 invmod .
null
J, 28 bytes
4 :'(1=x+.y)*x y&|@^<:5 p:y'
Uses Euler's theorem. Returns 0 if the inverse does not exist.
Explanation
4 :'(1=x+.y)*x y&|@^<:5 p:y' Input: a (LHS), b (RHS)
4 :' ' Define an explicit dyad - this is to use the special
form `m&|@^` to perform modular exponentiation
y Get b
5 p: Euler totient
<: Decrement
x Get a
^ Exponentiate
y&|@ Modulo b
x+.y GCD of a and b
1= Equals 1
* Multiply
Pyth, 10 bytes
3 bytes saved thanks to @Jakube .
xm%*szdQQ1
Returns -1 for no multiplicative inverse.
Code Breakdown
xm%*szdQQ1 Let Q be the first input.
m Q This maps over [0 ... Q) with a variable d.
*szd Now d is multiplied by the evaluated second input.
% Q Now the remained modulo Q is retrieved.
x 1 Then, the first index of 1 is retrieved from that mapping.
Pyth, (削除) 15 (削除ここまで) 13 bytes
KEhfq1%*QTKSK
Throws an exception in case no multiplicative inverse exists.
Pyth, 15 bytes
Iq1iQKEfq1%*QTK
This adds lots of bytes for handling the case where no such number exists. The program can be shortened significantly if that case would not need to be handled:
fq1%*QTK
-
\$\begingroup\$ 2 bytes saved with
KExm%*QdKK1\$\endgroup\$Jakube– Jakube2017年08月25日 06:51:07 +00:00Commented Aug 25, 2017 at 6:51 -
\$\begingroup\$ Or 3 bytes if you swap the order of inputs:
xm%*szdQQ1\$\endgroup\$Jakube– Jakube2017年08月25日 06:53:03 +00:00Commented Aug 25, 2017 at 6:53 -
\$\begingroup\$ @Jakube Thanks a lot, editing! \$\endgroup\$Mr. Xcoder– Mr. Xcoder2017年08月25日 07:26:12 +00:00Commented Aug 25, 2017 at 7:26
-
\$\begingroup\$ How does this work? \$\endgroup\$user41805– user418052018年11月20日 20:04:41 +00:00Commented Nov 20, 2018 at 20:04
-
\$\begingroup\$ @Cowsquack I've added a completely primitive code breakdown but rn I don't have time to include a complete explanation. Hopefully it is clear enough for now but I'll try to add a more complete explanation soon. \$\endgroup\$Mr. Xcoder– Mr. Xcoder2018年11月21日 14:42:21 +00:00Commented Nov 21, 2018 at 14:42
Python 3.8, 22 bytes
lambda a,b:pow(a,-1,b)
Obligatory Python 3.8+ builtin. Outputs the result, or gives the error ValueError: base is not invertible for the given modulus if there is no result.
Explanation:
To quote the Python 3.8 release notes:
For integers, the three-argument form of the pow() function now permits the exponent to be negative in the case where the base is relatively prime to the modulus. It then computes a modular inverse to the base when the exponent is -1, and a suitable power of that inverse for other negative exponents. For example, to compute the modular multiplicative inverse of 38 modulo 137, write:
>>> pow(38, -1, 137) 119 >>> 119 * 38 % 137 1Modular inverses arise in the solution of linear Diophantine equations. For example, to find integer solutions for
4258x + 147y = 369, first rewrite as4258x ≡ 369 (mod 147)then solve:>>> x = 369 * pow(4258, -1, 147) % 147 y = (4258 * x - 369) // -147 4258 * x + 147 * y 369(Contributed by Mark Dickinson in bpo-36027.)
C (gcc), 115 bytes
#define L long long
L g(L a,L b,L c,L d){return a?g(b%a,a,d-b/a*c,c):b-1?0:d;}L f(L a,L b){return(g(a,b,1,0)+b)%b;}
Extended Euclidean algorithm, recursive version
C (gcc), 119 bytes
long long f(a,b,c,d,t,n)long long a,b,c,d,t,n;{for(c=1,d=0,n=b;a;a=t)t=d-b/a*c,d=c,c=t,t=b%a,b=a;return b-1?0:(d+n)%n;}
Extended Euclidean algorithm, iterative version
C (gcc), (削除) 48 110 (削除ここまで) 104 bytes
#define f(a,b)g(a,b,!b,1,b)
long g(a,b,c,d,n)long a,b,c,d,n;{a=a?g(b%a,a,d,c-(b-b%a)/a*d):!--b*(c+n)%n;}
This should work with all inputs (that fit within a long) within 60 seconds.
Edit. I'm already abusing the n variable so I might as well assume that gcc puts the first assignment in %rax.
-
2\$\begingroup\$ Alas, this gives wrong results even for fairly small inputs due to integer overflow inside the loop. For example,
f(3,1000001)returns 717, which is obviously nonsense (the correct answer is 333334). Also, even if this bug was fixed by using a wider integer type, this brute-force approach would certainly time out for some of the larger test cases given in the challenge. \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年08月25日 01:20:15 +00:00Commented Aug 25, 2017 at 1:20
APL (Dyalog Unicode), 36 (削除) 38 (削除ここまで) bytes
{⌈/i×ばつ1=⍵|(i←⍳⍵)×ばつ⍵|⍺}
Explanation:
⍵|⍺} ⍝ Get ⍺ mod ⍵
(i←⍳⍵)×ばつ ⍝ Multiply the result by all numbers up to ⍵
⍵| ⍝ Take result mod ⍵
i×ばつ1= ⍝ Find all numbers (1,⍵) where the mod is 1
{⌈/ ⍝ And take the largest
Much thanks to Adam in the APL Orchard chatroom for the help with this one!
Formula obtained from this site
First iteration:
{((⍵|⍺),⍵)×ばつ1=( ̄1↑⍺)×ばつ⊃⍺}⍳⍵}
-
1\$\begingroup\$ what about larger tests? the challenge says: "The program should finish at some point, and should solve each test case in less than 60 seconds" \$\endgroup\$ngn– ngn2020年02月17日 16:15:18 +00:00Commented Feb 17, 2020 at 16:15
-
1\$\begingroup\$ we usually count 1 char = 1 byte in apl \$\endgroup\$ngn– ngn2020年02月17日 16:15:50 +00:00Commented Feb 17, 2020 at 16:15
[Pyt], 1 byte
ɯ
Takes inputs in the order b a (on separate lines). Outputs None if there is no such multiplicate inverse. Gotta love built-ins.
J, 3 bytes
%m.
J9.05 added the new modular arithmetic primitive, which reserves the monadic form for % and %. for returning the modular inverse. Throws a domain error if the inverse cannot be found.
This produces an adverb. b is the left arg and a is the right arg
Python 2 + sympy, 74 bytes
from sympy import*
def f(a,m):i,_,g=numbers.igcdex(a,m);return g==1and i%m
Axiom, 45 bytes
f(x:PI,y:PI):NNI==(gcd(x,y)=1=>invmod(x,y);0)
0 for error else return z with x*z Mod y =1
Python 2, 52 bytes
-3 bytes thanks to Mr. Xcoder.
f=lambda a,b,i=1:i*a%b==1and i or i<b and f(a,b,i+1)
Outputs False on no solution and errors out as b gets larger.
Embedded TIO
I'm just testing out iframes in Stack Snippets and they work absolutely fantastic.
html,body{height:100%;}iframe{height:100%;width:100%;border:none;}
<iframe src="https://tio.run/##PY3BCsIwEETv/Yq5CEndy6ZotbhfIh4SanBB09Lm4tdHU8HTvIHhzfzOjym5UqI8/SuMHp4CqfCgrd8FEfZphGJaoJeAWqLZJnu2Jd/XvEJwNUxwlmA6wrFmTzj1FdzhT4QzV@DuR7emidULTdhMA@ZFU/4@tGrLBw"></iframe>
-
\$\begingroup\$ I'm not certain this works, can't
i*a%bbe0? \$\endgroup\$2017年08月24日 16:29:21 +00:00Commented Aug 24, 2017 at 16:29 -
1\$\begingroup\$ Fails with "maximum recursion depth exceeded" error for input
(31,73714876143). \$\endgroup\$Ilmari Karonen– Ilmari Karonen2017年08月25日 01:09:34 +00:00Commented Aug 25, 2017 at 1:09
JavaScript (ES6), (削除) 42 (削除ここまで) (削除) 41 (削除ここまで) (削除) 39 (削除ここまで) 38 bytes
Outputs false for no match. Will throw a overflow error as the second number gets to be too large.
x=>y=>(g=z=>x*z%y==1?z:z<y&&g(++z))(1)
Jelly, 27 bytes
×ばつgỊ\
Uses Euler's theorem with modular exponentiation. Since Jelly doesn't have a builtin to perform modular exponentiation, it had to be implemented, and it took most of the bytes.
Axiom, 99 bytes
w(a,b,x,u)==(a=0=>(b*b=1=>b*x;0);w(b rem a,a,u,x-u*(b quo a)));h(a,b)==(b=0=>0;(b+w(a,b,0,1))rem b)
it use the function h(); h(a,b) return 0 if error [not exist inverse] otherwise it return the z such that a*z mod b = 1 This would be ok even if arguments are negative...
this would be the general egcd() function that retunr a list of int (so they can be negative too)
egcd(aa:INT,bb:INT):List INT==
x:=u:=-1 -- because the type is INT
(a,b,x,u):=(aa,bb,0,1)
repeat
a=0=>break
(q,r):=(b quo a, b rem a)
(b,a,x,u):=(a,r,u,x-u*q)
[b,x, (b-x*aa)quo bb]
this is how use it
(7) -> h(31,73714876143)
(7) 45180085378
Type: PositiveInteger
i find the base algo in internet from https://pastebin.com/A13ybryc
APL(NARS), 66 chars
{1≠↑k←{(a b)←⍵⋄b=0:a,1,0⋄(g x y)←∇b,b∣a⋄g×ばつ⌊a÷b}⍵:0⋄⍵[2]∣2⊃k}
In input one array of 2 elements: the first is the value to invert as examples. If no solution find it should return 0. Test:
f←{1≠↑k←{(a b)←⍵⋄b=0:a,1,0⋄(g x y)←∇b,b∣a⋄g×ばつ⌊a÷b}⍵:0⋄⍵[2]∣2⊃k}
f 1 2
1
f 3 6
0
f 7 87
25
f 13 91
0
f 19 1212393831
701912218
f 31 73714876143
45180085378
f 3 73714876143
0