Розподіліть множину Гаусса


23

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
За словами Вольфрама Альфи, 6840+585iмає неправильний перелік факторів, як 5це не є прем'єр-міністром Гаусса. Натомість повертається -1-2i, 1+4i, 2+i, 3, 3, 6+i, 6+i. Джерело
Ink Value

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


коли це говорить "тримай тільки Гаусса", чи означає це "тримати тільки Прими"?
Дон яскравий

@donbright ні, це стосується збереження лише тих складних чисел із цілими реальними та складними компонентами
fireflame241

@ fireflame241 о, я бачу зараз! велике дякую
нехай яскравий

5

Ruby , 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³ байт при змішуванні вкладок та пробілів: завдяки ов

Деякі пояснення рекурсивно розкладають комплекс на два комплекси, поки не можливе розкладання ...


Ну, час у TIO збільшується на більші входи, але він коротший, ніж моя відповідь Ruby ... поки що . Також def f(Z,s=[])має врятувати вас персонаж
Value Ink

@ValueInk так, це повільніше, ніж ваше рубінове рішення
mdahmoune

2
Цікава картина з відступом ...
Ерік Аутгольфер

Багатофункціональні аргументи @ValueInk економить більше байтів :)
mdahmoune

1
Ви можете зменшити кількість байтів, змішавши вкладки та пробіли
до

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% правильно, але це здається правильним для великого кола тестів. Це не менше, ніж Jelly, але принаймні менше, ніж інтерпретовані мови (поки що). Це також здається більш швидким і може працювати через входи в розмір мільярда менше ніж за секунду. Наприклад, 1234567890 + 3141592650i коефіцієнти як (-9487 + 7990i) (- 1 + -1i) (- 395 + 336i) (2 + -1i) (1 + 1i) (3 + 0i) (3 + 0i) (4+ 1i) (- 1 + 1i) (- 1 + 2i), (натисніть тут, щоб перевірити вольфрам альфа)

Це почалося з тієї ж ідеї, що і наївний факторинг цілих чисел, щоб пройти кожне число нижче відповідного цілого числа, побачити, чи воно розділене, повторити до завершення. Потім, надихнувшись іншими відповідями, він перетворювався ... він неодноразово фактує елементи у векторі. Це роблять це досить багато разів, але не "поки" нічого. Кількість ітерацій було вибрано, щоб охопити хороший фрагмент розумних вкладень.

Він все ще використовує "(mod b) == 0", щоб перевірити, чи ділиться одне ціле число на інше (для гауссів ми використовуємо вбудований модуль гаусса Руста, і вважаємо "0" нормою == 0), проте перевірка на "норму ( a / b)! = 1 'запобігає діленню "занадто багато", в основному дозволяє заповнити отриманий вектор лише праймерами, але не зводить жодного елемента вектора до одиниці (0-i, 0 + i, -1 + 0i, 1 + 0i) (що заборонено питанням).

Межі for-loop були встановлені в експерименті. y переходить від 1 вгору, щоб запобігти паніці поділу на нуль, і x може перейти від -999 до 0 завдяки дзеркальному відображенню гауссів над квадрантами (я думаю?). Що стосується обмежень, то в початковому запитанні не було вказано допустимого діапазону введення / виводу, тому передбачається "розумний розмір введення" ... (Редагувати ... однак я не точно впевнений, як розрахувати, за якого числа це буде починають "провалюватися", я думаю, є цілі цілі Гаусса, які не поділяються нічим нижче 999, але все ще для мене дивно малі)

Спробуйте дещо неопущену версію на play.rust-lang.org


3

Perl 6 , 141 124 байт

Завдяки Джо Кінгу за -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(тобто поточний коефіцієнт, розділений на число), це ціле число
Джо Кінг,

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 побив желе 😲 (я не очікую, що це триватиме)

 .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-х. Він буде працювати більше часу, тому якщо ви працюєте локально, він повинен працювати без проблем.
Сок
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.