Find the inverse of a 3 by 3 matrix

Challenge

Given nine numbers, a, b, c, d, e, f, g, h, i, as input which correspond to the square matrix:

$$\mathbf{M} = \begin{pmatrix}a& b& c\\ d& e& f\\ g& h& i\end{pmatrix}$$

Find the inverse of the matrix, $\mathbf{M}^{-1}$ and output its components.

Inverse Matrix

The inverse of a matrix 3 by 3 obeys the following equation:

$$\mathbf{MM}^{-1} = \mathbf{M}^{-1}\mathbf{M} = \mathbf{I} = \begin{pmatrix}1&0&0\\0&1&0\\0&0&1\end{pmatrix}$$

And can be calculated as:

$$\mathbf{M}^{-1} = \frac{1}{\det(\mathbf{M})}\mathbf{C}^T$$

Where $\mathbf{C}$ is the matrix of cofactors:

$$\mathbf{C}=\begin{pmatrix}ei-fh&fg-di&dh-eg\\ch-bi&ai-cg&bg-ah\\bf-ce&cd-af&ae-bd\end{pmatrix}$$

And $\mathbf{C}^T$ is the transpose of $\mathbf{C}$:

$$\mathbf{C}^T = \begin{pmatrix}ei-fh&ch-bi&bf-ce\\fg-di&ai-cg&cd-af\\dh-eg&bg-ah&ae-bd\end{pmatrix}$$

And $\det(\mathbf{M})$ is the determinant of $\mathbf{M}$:

$$\det(\mathbf{M}) = a(ei-fh)-b(di-fg)+c(dh-eg)$$

Worked Example

For example, let's say the input is 0, -3, -2, 1, -4, -2, -3, 4, 1. This corresponds to the matrix:

$$\mathbf{M} = \begin{pmatrix}0&-3&-2\\1&-4&-2\\-3&4&1\end{pmatrix}$$

Firstly, let's calculate what's known as the determinant using the formula above:

$$\det(\mathbf{M}) = 0(-4\times1-(-2)\times4) - (-3)(1\times1-(-2)\times-3) + (-2)(1\times4-(-4)\times-3) = 1$$

Next let's calculate the matrix of cofactors:

$$\mathbf{C} = \begin{pmatrix}-4\times1-(-2)\times4& -(1\times1-(-2)\times-3)&1\times4-(-4)\times-3\\-(-3\times1-(-2)\times4)&0\times1-(-2)\times-3&-(0\times4-(-3)\times-3)\\-3\times-2-(-2)\times-4&-(0\times-2-(-2)\times1)&0\times-4-(-3)\times1\end{pmatrix}$$

$$= \begin{pmatrix}4&5&-8\\-5&-6&9\\-2&-2&3\end{pmatrix}$$

We then need to transpose $\mathbf{C}$ (flip the rows and columns) to get $\mathbf{C}^T$:

$$\mathbf{C}^T = \begin{pmatrix}4&-5&2\\5&-6&-2\\-8&9&3\end{pmatrix}$$

Finally, we can find the inverse as:

$$\mathbf{M}^{-1} = \frac{1}{\det(\mathbf{M})}\mathbf{C}^T = \frac{1}{1}\begin{pmatrix}4&-5&2\\5&-6&-2\\-8&9&3\end{pmatrix}=\begin{pmatrix}4&-5&2\\5&-6&-2\\-8&9&3\end{pmatrix}$$

So the output would be 4, -5, -2, 5, -6, -2, -8, 9, 3.

Rules

• The given matrix will always have an inverse (i.e. non-singular). The matrix may be self-inverse

• The given matrix will always be a 3 by 3 matrix with 9 integers

• The numbers in the input will always be integers in the range $-1000 \leq n \leq 1000$

• Non-integer components of the matrix may be given as a decimal or a fraction

Examples

Input > Output
1, 0, 0, 0, 1, 0, 0, 0, 1 > 1, 0, 0, 0, 1, 0, 0, 0, 1
0, -3, -2, 1, -4, -2, -3, 4, 1 > 4, -5, -2, 5, -6, -2, -8, 9, 3
1, 2, 3, 3, 1, 2, 2, 1, 3 > -1/6, 1/2, -1/6, 5/6, 1/2, -7/6, -1/6, -1/2, 5/6
7, 9, 4, 2, 7, 9, 3, 4, 5 > -1/94, -29/94, 53/94, 17/94, 23/94, -55/94, -13/94, -1/94, 31/94


Winning

The shortest code in bytes wins.

Jelly, 3 bytes

æ*-


Try it online!

Assuming we can take input and provide as a 2D list of integers. If a flat list of integers is really required for both input and output, then this works for 6 bytes.

• Explanation (I don't think it's worth including in the answer): æ* - matrix exponentiation, - - exponent, which equals $-1$. - is a syntax character for negative literals but it defaults to $-1$ when there is no number right after it. – Mr. Xcoder Jul 18 '18 at 19:17
• Comments aren't necessarily meant to be long lived. If you're including an explanation in the comments, you should move it to the answer instead. – Poke Jul 18 '18 at 19:22

JavaScript (ES6), 123 bytes

Saved 2 bytes thanks to @Mr.Xcoder
Saved 1 byte thanks to @ETHproductions

Takes input as 9 distinct values.

(a,b,c,d,e,f,g,h,i)=>[x=e*i-h*f,c*h-b*i,b*f-c*e,y=f*g-d*i,a*i-c*g,d*c-a*f,z=d*h-g*e,g*b-a*h,a*e-d*b].map(v=>v/=a*x+b*y+c*z)


Try it online!

• Hey, i've allowed built-in matrix functions now. That is, if JS has any – Beta Decay Jul 18 '18 at 17:25
• @BetaDecay JS has none. :-) – Arnauld Jul 18 '18 at 17:28
• Are those brackets really needed? – Mr. Xcoder Jul 18 '18 at 18:09

MATL, 54 bytes

th3LZ)t,3:q&XdpswP]w-lw/GtY*tXdsGXdsUw-IXy*2/+GtXds*-*


Try it online!

Just to keep it interesting, doesn't use the inbuilt matrix division or determinant functions to do it.

Instead, computes the determinant using the Rule of Sarrus.

And the adjugate (transposed cofactor matrix) using Cayley–Hamilton formula.

$${\displaystyle \operatorname {adj} (\mathbf {A} )={\frac {1}{2}}\left((\operatorname {tr} \mathbf {A} )^{2}-\operatorname {tr} \mathbf {A} ^{2}\right)\mathbf {I} _{3}-\mathbf {A} \operatorname {tr} \mathbf {A} +\mathbf {A} ^{2}.}$$

Commented code:

% Finding determinant
th    % concatenate the matrix to itself sideways
3LZ)  % chop off the last column (since the Rule of Sarrus doesn't need it)
t     % duplicate this matrix (say S)
,     % do this twice:
3:q&Xd  % get the first three diagonals of S
ps      % multiply each diagonal's values and add the results
wP      % switch and flip the matrix (to get the popposing diagonals next time)
]w    % close loop, switch to have correct order of sums
-     % subtract - we now have the determinant
lw/   % invert that

% Finding adjugate using Cayley–Hamilton formula
GtY*  % A^2 term (last term of the formula)
tXds  % trace(A^2) for term 1 of formula
GXdsU % (trace(A))^2 for term1 of formula
w-    % (trace(A))^2 - trace(A^2)
IXy*  % multiply that by the identity matrix
2/    % divide that by 2 - term 1 complete
+
GtXds* % A*trA for term 2 of formula
-      % subtract to get adj(A)

*      % multiply by the inverse of determinant we found earlier
% implicit output


We could go even more insane purer by replacing the matrix multiplication GtY* done for $A^2$, with something like 3:"Gt!@qYS*!s] 3$v t&v 3:K-&Xd (Try it on MATL Online). The more direct and obvious way: 4 bytes -1Y^  Try it online! (-1 byte thanks to @Luis Mendo.) -1 - Push the literal -1 Y^ - Raise input to that power (implicit input, implicit output) • Interesting, I never knew it was called the “Rule of Sarrus”. My teacher taught us it, but he had made it up himself while at uni. – Beta Decay Jul 18 '18 at 23:44 • @LuisMendo Thanks, replaced the short version (tbh the previous version was just a blind implementation of the MATL manual's suggestion for inverse, no actual thinking went into that one :) ). For the long version, I think it's a tiny bit clearer to leave it as such, enough to be worth taking a 1 byte hit. – sundar Jul 19 '18 at 12:28 • @sundar Heh, I didn't even remember that suggestion. I'll add the suggestion of matrix power too – Luis Mendo Jul 19 '18 at 12:31 APL(Dyalog Classic),1 byte ⌹  Try it online! if a flat lis is required this is 8 bytes ,∘⌹3 3∘⍴  Try it online! • Welcome to PPCG! – Beta Decay Jul 18 '18 at 19:07 J, 2 bytes %.  Just a built-in primitive Try it online! R, 51 35 27 8 5 bytes solve  Try it online! First go at doing one of these golf challenges. Sorry if my formatting is wrong! Saved a total additional 11 bytes thanks to Giuseppe! Saved an additional 19 bytes thanks to JAD! • Welcome to PPCG! – Beta Decay Jul 18 '18 at 20:40 • Removed the parameter variable names from the matrix function which subtracted 16 bytes! – Robert S. Jul 18 '18 at 20:56 • Nice! You can remove most of the variables to save bytes since you're really just chaining the operations together: try it online! – Giuseppe Jul 18 '18 at 21:38 • If you're going to use solve, the solution is just solve, as it fulfills all the requirements of the question. It takes a matrix as input and returns a matrix. – JAD Jul 20 '18 at 12:21 • like this – Giuseppe Jul 20 '18 at 16:18 Python 2, 139 bytes def F(a,b,c,d,e,f,g,h,i):x=e*i-f*h;y=f*g-d*i;z=d*h-e*g;print[j/(a*x+b*y+c*z)for j in x,c*h-b*i,b*f-c*e,y,a*i-c*g,c*d-a*f,z,b*g-a*h,a*e-b*d]  Try it online! (Has return instead of print for ease of testing.) Clean, 143 bytes import StdEnv$a b c d e f g h i#p=e*i-h*f
#q=f*g-d*i
#r=d*h-g*e
=[v/(a*p+b*q+c*r)\\v<-[p,c*h-b*i,b*f-c*e,q,a*i-c*g,d*c-a*f,r,g*b-a*h,a*e-d*b]]


Try it online!

Pari/GP, 6 bytes

m->1/m


Takes multiplicative inverse in the matrix ring $\mathrm{M}_n$.

Try it online!

Perl, 226 + 4 (-plF, flag) = 230 bytes

$_=join', ',map$_/($a*$x+$b*$y+$c*$z),$x=($e=$F[4])*($i=$F[8])-($f=$F[5])*($h=$F[7]),($c=$F[2])*$h-($b=$F[1])*$i,$b*$f-$c*$e,$y=$f*($g=$F[6])-($d=$F[3])*$i,($a=$F[0])*$i-$c*$g,$c*$d-$a*$f,$z=$d*$h-$e*$g,$b*$g-$a*$h,$a*$e-$b*$d


Perl 5, 179 bytes

sub{($a,$b,$c,$d,$e,$f,$g,$h,$i)=@_;map$_/($a*$x+$b*$y+$c*$z),$x=$e*$i-$f*$h,$c*$h-$b*$i,$b*$f-$c*$e,$y=$f*$g-$d*$i,$a*$i-$c*$g,$c*$d-$a*$f,$z=$d*$h-$e*$g,$b*$g-$a*$h,$a*$e-$b*\$d}


Python 3, 77 bytes

import numpy
lambda l:(numpy.matrix(l).reshape(-1,3)**-1).ravel().tolist()[0]


Takes input as a flat list.

It's 63 bytes if input is taken as a 2D array:

import numpy
lambda l:(numpy.matrix(l)**-1).ravel().tolist()[0]


Noether, 168 bytes

I~aI~bI~cI~dI~eI~fI~gI~hI~iei*fh*-a*di*fg*-b*-dh*eg*-c*+~zei*fh*-z/P","~nPch*bi*-z/PnPbf*ce*-z/PnPfg*di*-z/PnPai*cg*-z/PnPcd*af*-z/PnPdh*eg*-z/PnPbg*ah*-z/PnPae*bd*-z/P


Try it online

=MINVERSE(A1:C3)


Input is in the range A1:C3

Built-ins are boring

Clojure, 165 bytes

(fn[a b c d e f g h i](let[M map C(M -(M *[e f d c a b b c a][i g h h i g f d e])(M *[f d e b c a c a b][h i g i g h e f d]))](for[i C](/ i(apply +(M *[a b c]C))))))


I'm sorry this outputs C in transpose, and I'm feeling lazy to re-do those long character sequences to fix it at the moment.

APL (Dyalog), 7 bytes

,⌹3 3⍴⎕


Takes input as a flat list and outputs as a flat list

Try it online!