แยกตัวประกอบ Gaussian จำนวนเต็ม


23

Gaussian จำนวนเต็มคือตัวเลขที่ซับซ้อนที่มีจริงและส่วนจินตภาพเป็นจำนวนเต็ม

จำนวนเต็ม Gaussian เช่นจำนวนเต็มธรรมดาสามารถแสดงเป็นผลิตภัณฑ์ของจำนวนเฉพาะ Gaussian ในลักษณะที่ไม่ซ้ำกัน ความท้าทายที่นี่คือการคำนวณองค์ประกอบที่สำคัญของจำนวนเต็ม Gaussian ที่กำหนด

อินพุต: จำนวนเต็มแบบเกาส์ซึ่งไม่เท่ากับ 0 และไม่ได้เป็นหน่วย (เช่น 1, -1, i และ -i ไม่สามารถให้เป็นอินพุต) ใช้รูปแบบที่เหมาะสมตัวอย่างเช่น:

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

เอาท์พุท: รายการของเลขจำนวนเต็มแบบเกาส์ซึ่งเป็นจำนวนเฉพาะ (กล่าวคือไม่มีตัวใดตัวหนึ่งที่สามารถแสดงเป็นผลคูณของจำนวนเต็มแบบเกาส์ที่ไม่ใช่หน่วยสองหน่วย) และผลิตภัณฑ์มีค่าเท่ากับจำนวนอินพุต ตัวเลขทั้งหมดในรายการเอาท์พุทจะต้องไม่สำคัญคือไม่ใช่ 1, -1, i หรือ -i สามารถใช้รูปแบบเอาต์พุตที่เหมาะสมได้ ไม่ควรจะเหมือนกับรูปแบบอินพุต

หากรายการเอาท์พุทมีมากกว่า 1 องค์ประกอบก็จะสามารถแก้ไขเอาต์พุตที่ถูกต้องได้หลายรายการ ตัวอย่างเช่นสำหรับอินพุต 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?
หมึกมูลค่า

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
FYI 256=(1+i)**16ไม่ใช่(1+i)**8เพราะ256=2**8=(2i)**8และ2i=(1+i)**2
Shieru Asakoto

คำตอบ:


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


เมื่อสิ่งนี้บอกว่า "Keep only Gaussian" หมายความว่า "Keep only Primes" หรือไม่?
ดอนสดใส

@ ดอนไบรท์ไม่มันหมายถึงการรักษาเฉพาะตัวเลขที่ซับซ้อนเหล่านั้นด้วยจำนวนจริงและส่วนประกอบที่ซับซ้อนจำนวนมาก
fireflame241

@ fireflame241 โอ้ฉันเห็นแล้วตอนนี้! ขอบคุณมาก ๆ
ดอนสดใส

5

Ruby , 258 256 249 246 + 8 = 264 257 254 ไบต์

ใช้-rprimeธง

Geez ช่างเป็นระเบียบ

ใช้อัลกอริทึมนี้จาก 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 ในปัจจัยการผลิตที่มีขนาดใหญ่ แต่ก็เป็นคำตอบที่สั้นกว่าทับทิมของฉัน ... สำหรับตอนนี้ นอกจากนี้def f(Z,s=[])ควรช่วยให้คุณประหยัดอักขระ
Value Ink

@ValueInk ใช่ช้ากว่าโซลูชันทับทิมของคุณ
mdahmoune

2
รูปแบบที่น่าสนใจพร้อมการเยื้อง ...
Erik the Outgolfer

@ValueInk อาร์กิวเมนต์ของฟังก์ชันหลายตัวช่วยประหยัดไบต์ได้มากขึ้น :)
mdahmoune

1
คุณสามารถลดจำนวนไบต์ของคุณโดยการผสมแท็บและช่องว่าง
OVS

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% ว่าใช้งานได้ถูกต้อง 100% แต่ดูเหมือนว่าจะถูกต้องสำหรับการทดสอบที่หลากหลาย นี่ไม่ใช่เล็กกว่าเจลลี่ แต่อย่างน้อยก็เล็กกว่าภาษาที่ตีความ (จนถึงปัจจุบัน) ดูเหมือนว่าจะเร็วขึ้นและสามารถทำงานผ่านอินพุตหนึ่งพันล้านขนาดในเวลาน้อยกว่าหนึ่งวินาที ตัวอย่างเช่น 1234567890 + 3141592650i เป็นปัจจัย (-9487 + 7990i) (- 1 + -1i) (- 395 + 336i) (2 + -1i) (1 + 1i) (3 + 0i) (3 + 0i) (3 + 0i) (4 + 1i) (- 1 + 1i) (- 1 + 2i), (คลิกที่นี่เพื่อทดสอบ wolfram alpha)

สิ่งนี้เริ่มต้นจากแนวคิดเดียวกันกับแฟ็กตอริ่งของจำนวนเต็มที่ไร้เดียงสาหากต้องการดูแต่ละจำนวนด้านล่างของจำนวนเต็มในคำถามดูว่ามันหารแล้วทำซ้ำจนกว่าจะเสร็จ จากนั้นได้แรงบันดาลใจจากคำตอบอื่น ๆ มันแปรเปลี่ยน ... มันซ้ำกับปัจจัยในรายการเวกเตอร์ มันเป็นจำนวนครั้งที่ดี แต่ไม่ใช่ 'จนถึง' อะไรก็ได้ จำนวนของการวนซ้ำได้รับเลือกเพื่อให้ครอบคลุมอินพุตที่เหมาะสม

มันยังคงใช้ "(a mod b) == 0" เพื่อทดสอบว่าจำนวนเต็มหนึ่งหารอีก (สำหรับ Gaussians เราใช้ builtin Rust gaussian modulo และพิจารณา "0" เป็น norm == 0) อย่างไรก็ตามการตรวจสอบ 'norm ( a / b)! = 1 'ป้องกันการหาร "มากเกินไป" โดยทั่วไปทำให้เวกเตอร์ที่ได้นั้นเต็มไปด้วยเฉพาะช่วงเวลา แต่ไม่นำองค์ประกอบใด ๆ ของเวกเตอร์ลงไปเป็นเอกภาพ (0-i, 0 + i, -1 + 0i, 1 + 0i) (ซึ่งเป็นสิ่งต้องห้ามตามคำถาม)

พบขีด จำกัด for-loop ผ่านการทดสอบ y เพิ่มขึ้นจาก 1 ขึ้นไปเพื่อป้องกันการตื่นตระหนกแบบแบ่งศูนย์และ x สามารถเปลี่ยนได้ตั้งแต่ -999 ถึง 0 ด้วยการสะท้อนของ Gaussians เหนือจตุภาค (ฉันคิดว่า?) คำถามเดิมไม่ได้ระบุช่วงที่ถูกต้องของอินพุต / เอาท์พุตดังนั้นจึงถือว่า "ขนาดอินพุตที่เหมาะสม" ... (แก้ไข ... อย่างไรก็ตามฉันไม่แน่ใจว่าจะคำนวณได้อย่างไรว่าจะใช้จำนวนใด เริ่มที่จะ "ล้มเหลว" ฉันคิดว่ามีจำนวนเต็มแบบเกาส์ซึ่งไม่สามารถหารด้วยสิ่งใด ๆ ที่ต่ำกว่า 999 แต่ยังเล็กสำหรับฉัน)

ลองใช้เวอร์ชันที่ไม่ได้รับความนิยมใน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

Pyth , 54 51 45 42 36 ไบต์

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

ลองออนไลน์!

รับข้อมูลในรูปแบบ1+2j- หมดจดตัวเลขจริงหรือจินตนาการสามารถละเว้นส่วนประกอบอื่น ๆ (เช่น9, 2j) เอาท์พุทเป็นรายการของตัวเลขที่ซับซ้อนคั่นด้วยบรรทัดใหม่ในรูปแบบที่(1+2j)มีตัวเลขในจินตนาการอย่างหมดจดแยกส่วนจริง

วิธีนี้ใช้การแบ่งเส้นทางแบบง่ายสร้างจำนวนเต็มแบบเกาส์ทั้งหมดที่มีขนาดมากกว่า 1 และน้อยกว่าค่าปัจจุบันบวกกับค่าของมันเอง สิ่งเหล่านี้จะถูกกรองเพื่อรักษาค่าที่เป็นปัจจัยของค่าและขนาดที่เล็กที่สุดจะถูกเลือกเป็นปัจจัยสำคัญต่อไป นี่คือเอาต์พุตและค่าจะถูกหารด้วยค่าเพื่อสร้างค่าสำหรับการวนซ้ำครั้งถัดไป

นอกจากนี้ Pyth beating 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 เนื่องจากมีขีด จำกัด การประมวลผล 60 วินาที มันจะทำงานกับเวลามากขึ้นดังนั้นถ้าคุณใช้มันในเครื่องมันควรจะทำงานได้โดยไม่มีปัญหา
Sok
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.