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


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.