分解高斯整数


23

一个高斯整数是一个复杂的数字,其实虚部是整数。

像普通整数一样,高斯整数可以以独特的方式表示为高斯素数的乘积。这里的挑战是计算给定高斯整数的素数。

输入:高斯整数,不等于0,也不是单位(即1,-1,i和-i不能作为输入)。使用任何明智的格式,例如:

  • 4-5i
  • -5 * j + 4
  • (4,-5)

输出:高斯整数列表,它们是质数(即,没有一个可以表示为两个非单位高斯整数的乘积),并且其乘积等于输入数。输出列表中的所有数字都必须是平凡的,即不能为1,-1,i或-i。可以使用任何明智的输出格式。它不必与输入格式相同。

如果输出列表中有多个元素,则可能有几个正确的输出。例如,对于输入9,输出可以是[3,3]或[-3​​,-3]或[3i,-3i]或[-3​​i,3i]。

测试用例,(从此表中获取;每个测试用例2行)

2
1+i, 1-i

3i
3i

256
1+i,1+i,1+i,1+i,1+i,1+i,1+i,1+i,1+i,1+i,1+i,1+i,1+i,1+i,1+i,1+i

7+9i
1+i,2−i,3+2i

27+15i
1+i,3,7−2i

6840+585i
-1-2i, 1+4i, 2+i, 3, 3, 6+i, 6+i

不允许使用用于分解高斯整数的内置函数。但是,允许通过内置函数分解普通整数。


应该3i3,i还是返回3i
价值墨水

3i是正确的答案,因为i它不是素数。我已经更新了测试案例,以使其更加清晰。
anatolyg

-3-2j,2-1j,-1-1j是7 + 9j分解的正确答案吗?
mdahmoune

4
根据沃尔夫拉姆·阿尔法(Wolfram Alpha)的说法,6840+585i错误列出的因素5不是高斯素数。而是返回-1-2i, 1+4i, 2+i, 3, 3, 6+i, 6+i来源
价值墨水

1
仅供参考,256=(1+i)**16不是(1+i)**8因为256=2**8=(2i)**82i=(1+i)**2
Shieru Asakoto

Answers:


4

果冻61 55字节

Ḟ,Ċ1ḍP
Ḟ,ĊḤp/-,1p`¤×€×1,ıFs2S€⁸÷ÇÐfỊÐḟ1;Ṫð,÷@\ḟ1
Ç€F$ÐL

在线尝试!(页眉和页脚格式化输出)

-6个字节,感谢@EricTheOutgolfer

怎么运行的

Ḟ,Ċ1ḍP  - helper function: determines if a complex number is Gaussian
Ḟ,Ċ       - real, complex components
   1ḍ     - set each to if 1 divides them
     P    - all

Ḟ,ĊḤp/-,1p`¤×€×1,ıFs2S€⁸÷ÇÐfỊÐḟ1;Ṫð,÷@\ḟ1 - helper: outputs a factor pair of the input
Ḟ,ĊḤ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
  ÇÐf                    - keep only Gaussian numbers (using helper function)
     ỊÐḟ                 - 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


当说“仅保留高斯”时,是“仅保留素数”吗?
唐明

@donbright不,它是指仅保留那些包含整数实和复杂分量的复数
fireflame241

@ fireflame241哦,我明白了!非常感谢您
唐明

5

红宝石258 256 249 246 + 8 = 264 257 254字节

使用-rprime标志。

哎呀,真是一团糟。

从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}

在线尝试!


5

Python 2中250个 239 223 215字节

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:])

在线尝试!

  • 使用多功能参数时为-11个字节
  • 使用一个变量解析对时为-2²*²字节 (a,b)
  • 混合制表符和空格时为-2³字节:感谢ovs

一些解释将一个复合物递归分解为两个复合物,直到不可能分解为止。


嗯,在较大的输入上,它在TIO中超时,但是现在比我的Ruby答案短。另外,def f(Z,s=[])应该为您节省一个角色
价值墨水

@ValueInk是的,它比您的ruby解决方案慢
mdahmoune

2
带有压痕的有趣图案...
Erik the Outgolfer

@ValueInk多功能参数可节省更多字节:)
mdahmoune


3

-212字节

use num::complex::Complex as C;fn f(a:&mut Vec<C<i64>>){for _ in 0..2{for x in -999..0{for y in 1..999{for i in 0..a.len(){let b=C::new(x,y);if(a[i]%b).norm_sqr()==0&&(a[i]/b).norm_sqr()>1{a[i]/=b;a.push(b)}}}}}}

我不确定这是否100%正确,但对于大范围的测试似乎是正确的。它不比Jelly小,但至少比解释型语言小(到目前为止)。它似乎也更快,并且可以在不到一秒钟的时间内完成十亿级输入。例如1234567890 + 3141592650i因子为(-9487 + 7990i)(-1 + -1i)(-395 + 336i)(2 + -1i)(1 + 1i)(3 + 0i)(3 + 0i)(4+ 1i)(-1 + 1i)(-1 + 2i),(单击此处测试Wolfram alpha)

最初的想法与朴素的整数分解相同,它要遍历所讨论整数下面的每个数字,看看是否除以整数,直到完成为止。然后,在其他答案的启发下,它变形了……它反复将向量中的项目分解。它这样做的次数很多,但没有“直到”任何事情。选择了迭代次数以覆盖大量合理输入。

它仍然使用“(a mod b)== 0”来测试一个整数是否除以另一个整数(对于高斯,我们使用内置的Rust高斯模,并将“ 0”视为norm == 0),但是检查'norm( a / b)!= 1'可防止除法“太多”,基本上使所得向量仅用质数填充,而不能将向量的任何元素减至单位(0-i,0 + i,-1 + 0i,1 + 0i)(该问题禁止使用)。

循环极限是通过实验找到的。y从1上升到零以防止被零除的恐慌,而x由于高斯在象限上的镜像,x可以从-999到0。至于限制,最初的问题没有表明输入/输出的有效范围,因此假定使用“合理的输入大小” ...(编辑...但是我不确定如何计算该数字为多少)开始“失败”,我想有一些高斯整数不能被999以下的任何东西整除,但对我来说仍然小得令人惊讶)

尝试在一定程度上ungolfed版本play.rust-lang.org


3

Perl 6的141个 124字节

感谢Jo King的-17个字节

sub f($_){{$!=0+|sqrt .abs²-$^a²;{($!=$_/my \w=$^b+$a*i)==$!.floor&&.abs>w.abs>1>return f w&$!}for -$!..$!}for ^.abs;.say}

在线尝试!


这是如何运作的?地板是定制的模数吗?
唐明亮

1
@donbright该floor部分正在检查$_/w(即当前因子除以数字)是否为整数
Jo King

2

Pyth54 51 45 42 36字节

 .W>H1cZ
h+.aDf!%cZT1>#1.jM^s_BM.aZ2

在线尝试!

接受形式的输入 1+2j -纯实数或虚数可以忽略其它组件(例如92j)。输出是用换行符分隔的复数列表,形式为(1+2j),其中纯虚数省略了实部。

这使用简单的尾数除法,生成幅度大于1且小于当前值以及值本身的所有高斯整数。对它们进行过滤以保留那些作为值的因数,然后选择幅度最小的值作为下一个质数。输出结果,并将其除以该值以产生下一个迭代的值。

另外,Pyth击败了Jelly😲(不过我不希望它能持续下去)

 .W>H1cZ¶h+.aDf!%cZT1>#1.jM^s_BM.aZ2ZQ   Implicit: Q=eval(input())
                                         Newline replaced with ¶, trailing ZQ inferred
 .W                                  Q   While <condition>, execute <inner>, with starting value Q
   >H1                                   Condition function, input H
   >H1                                     Is magnitude of H > 1?
                                           This ensures loop continues until H is a unit, i.e. 1, -1, j, or -j)
      cZ¶h+.aDf!%cZT1>#1.jM^s_BM.aZ2Z    Inner function, input Z
                                .aZ        Take magnitude of Z

                             _BM           Pair each number in 0-indexed range with its negation
                            s              Flatten
                           ^       2       Cartesian product of the above with itself
                        .jM                Convert each pair to a complex number
                      #                    Filter the above to keep those element where...
                     > 1                   ... the magnitude is greater than 1 (removes units)
              f                            Filter the above, as T, to keep where:
                 cZT                         Divide Z by T
                %   1                        Mod real and imaginary parts by 1 separately
                                             If result of division is a gaussian integer, the mod will give (0+0j)
               !                             Logical NOT - maps (0+0j) to true, all else to false
                                           Result of filter are those gaussian integers which evenly divide Z
           .aD                             Sort the above by their magnitudes
          +                         Z      Append Z - if Z is ±1±1j, the filtered list will be empty
         h                                 Take first element, i.e. smallest factor
        ¶                                  Print with a newline
      cZ                                   Divide Z by that factor - this is new input for next iteration
                                         Output of the while loop is always 1 (or -1, j, or -j) - leading space suppesses output

这是非常有趣的,但它似乎对6840 + 585j超时
不要亮

@donbright在TIO上执行,因为它的处理限制为60s。它会花费更多时间,因此,如果您在本地运行它,则应该可以正常工作。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.