Factorize a Gaussian integer
Ruby, 258 256 249 246+8 = 264 257 254 bytes
Uses the -rprime
flag.
Geez, what a mess.
Uses this algorithm from stackoverflow.
->c{m=->x,y{x-y*eval("%d+%di"%(x/y).rect)};a=c.abs2.prime_division.flat_map{|b,e|b%4<2?(1..e).map{k=(2..d=b).find{|n|n**(~-b/2)%b==b-1}**(~-b/4)%b+1i;d,k=k,m[d,k]while k!=0;c/=d=m[c,d]==0?d:d.conj;d}:(c/=b<3?(b=1+1i)**e:b**e/=2;[b]*e)};a[0]*=c;a}
Try it online!
Python 2, 250 239 223 215 bytes
e,i,w=complex,int,abs
def f(*Z):
if Z:
z=Z[0];q=i(w(z));Q=4*q*q
while Q>0:
a=Q/q-q;b=Q%q-q;x=e(a,b)
if w(x)>1:
y=z/x
if w(y)>1 and y==e(i(y.real),i(y.imag)):f(x,y);z=Q=0
Q-=1
if z:print z
f(*Z[1:])
Try it online!
- -11 bytes when using Multiple Function Arguments
- -2²*² bytes when using one variable to parse couples
(a,b)
- -2³ bytes when mixing tabs and spaces: thanks to ovs
Some explanation recursively decompose a complex to two complexes until no decomposition is possible...
Jelly, 61 55 50 bytes
ÆiḤp/-,1p`¤×€×1,ıFs2S€⁸÷ÆiḞƑ$ƇỊÐḟ1;Ṫð,÷@\ḟ1
Ç€F$ÐL
Try it online! (Header and Footer formats the output)
-6 bytes thanks to @EricTheOutgolfer
-5 bytes thanks to @caird coinheringaahing
How it Works
ÆiḤp/-,1p`¤×€×1,ıFs2S€⁸÷ÆiḞƑ$ƇỊÐḟ1;Ṫð,÷@\ḟ1 - helper: outputs a factor pair of the input
ÆiḤp/ - creates a list of possible factors a+bi, a,b>=0
-,1p`¤×€ - extend to the other three quadrants
×1,ıFs2S€ - convert to actual complex numbers
⁸÷ - get quotient with input complex number
ÆiḞƑ$Ƈ - keep only Gaussian numbers (those unchanged when complex parts are floored)
ỊÐḟ - remove units (i,-i,1,-1)
1; - append a 1 to deal with primes having no non-unit factors
Ṫð,÷@\ - convert to a factor pair
ḟ1 - remove 1s
Ç€F$ÐL
Ç€ - factor each number
$ - and
F - flatten the list
ÐL - until factoring each number and flattening does not change the list