ガウス整数の因数分解


23

ガウス整数は、その実部と虚部の整数である複素数です。

ガウス整数は、通常の整数と同様に、ガウス素数の積として一意の方法で表すことができます。ここでの課題は、指定されたガウス整数の主な構成要素を計算することです。

入力:0ではなく、単位ではないガウス整数(つまり、1、-1、i、および-iは入力として指定できません)。賢明な形式を使用してください。例:

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

出力:素数(つまり、2つの非単位ガウス整数の積として表現できないもの)で、その積が入力数に等しいガウス整数のリスト。出力リストのすべての数値は、1、-1、i、または-iではなく、自明でないものでなければなりません。適切な出力形式を使用できます。入力形式と同じである必要はありません。

出力リストに複数の要素がある場合、いくつかの正しい出力が可能です。たとえば、入力9の場合、出力は[3、3]または[-3、-3]または[3i、-3i]または[-3i、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

ガウス整数を因数分解するための組み込み関数は許可されていません。ただし、組み込み関数による通常の整数の因数分解は許可されています。


必要がある3iとして返す3,i、または3i
バリューインク

3ii素数ではないため、正解です。テストケースを更新して、わかりやすくしました。
アナトリグ

-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
FYI、256=(1+i)**16ではない(1+i)**8ので、256=2**8=(2i)**82i=(1+i)**2
Shieru Asakoto

回答:


4

ゼリー61 55バイト

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

オンラインでお試しください!(ヘッダーとフッターは出力をフォーマットします)

@EricTheOutgolferのおかげで-6バイト

使い方

Ḟ,Ċ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

パイソン2250の 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バイト
  • 1つの変数を使用してカップルを解析する場合は-2²*²バイト (a,b)
  • タブとスペースを混在させる場合は-2³バイト:ovsのおかげ

一部の説明は、分解が不可能になるまで、複合体を2つの複合体に再帰的に分解します...


さて、TIOでは大きな入力でタイムアウトになりますが、Rubyの回答よりも短い... 今のところ。また、def f(Z,s=[])あなたのキャラクターを保存する必要があります
値インク

@ValueInkはい、それはあなたのルビーソリューションよりも遅いです
-mdahmoune

2
インデント付きの興味深いパターン...
エリックアウトゴルファー

@ValueInk複数の関数引数を使用すると、さらにバイトを節約できます:)
mdahmoune


3

さびバイト

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%正しく機能するかどうかは100%わかりませんが、広範囲のテストで正しいようです。これはJellyほど小さくはありませんが、少なくとも、これまでに解釈された言語よりも小さくなっています。また、高速であると思われ、10億規模の入力を1秒未満で処理できます。たとえば、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」をノルム== 0と見なします)、ただし、「norm( a / b)!= 1 'は「多すぎる」分割を防ぎ、基本的には結果のベクトルを素数のみで埋めることができますが、ベクトルの要素を1(0-i、0 + i、-1 + 0i、1 + 0i)(質問で禁止されています)。

forループの制限は、実験を通じて発見されました。yは1から0で除算するパニックを防ぎ、xは象限上のガウス分布のミラーリングのおかげで-999から0になります(と思いますか?)。制限に関しては、元の質問は有効な入力/出力の範囲を示していなかったので、「合理的な入力サイズ」が想定されます...(編集... 「失敗」し始めます。999未満では割り切れないが、私にとっては驚くほど小さいガウス整数があると思います)

play.rust-lang.orgで、やや手付かずのバージョンを試しください


3

Perl 6の141の 124バイト

-17バイトのJo Kingに感謝

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処理の制限が60秒であるため、TIOで実行されます。より多くの時間で動作するため、ローカルで実行している場合は問題なく動作するはずです。
ソク
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.