Найшвидший твітерний цілочисельний фактор


17

Завдання - знайти нетривіальний множник складеного числа.

Напишіть код, який знаходить нетривіальний коефіцієнт складеного числа якомога швидше, залежно від того, щоб ваш код був не більше 140 байт. Вихід повинен бути лише фактором, який ви знайшли.

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

Тестові приклади, в яких перераховані всі фактори (вам потрібно вивести лише один)

187: 11 17
1679: 23 73
14369648346682547857: 1500450271 9576890767
34747575467581863011: 3628273133 9576890767
52634041113150420921061348357: 2860486313 5463458053 3367900313
82312263010898855308580978867: 264575131106459 311111111111113
205255454905325730631914319249: 2860486313 71755440315342536873 
1233457775854251160763811229216063007: 1110111110111 1000000000063 1111111999999
1751952685614616185916001760791655006749: 36413321723440003717 48112959837082048697

Я не буду оцінювати вашу відповідь на наступний складний тестовий випадок, який може зацікавити тестування:

513231721363284898797712130584280850383: 40206835204840513073 12764787846358441471

Оцінка

Ваш бал - це комбінований час для врахування всіх тестових випадків, зазначених вище, із штрафом 10 хвилин за кожну невдалу факторизацію (всі округлені до найближчої секунди). Ваш код повинен працювати і для інших цілих чисел, тобто не слід просто жорстко кодувати ці відповіді.

Я зупиню ваш код через 10 хвилин.

Якщо двоє людей отримують однаковий бал, то перша відповідь виграє.

Обмеження

Ваш код не може використовувати будь-яку вбудовану або бібліотечну функцію, яка виконує цілочисельну факторизацію. Можна припустити, що вхід займає менше 256 біт. Усі вхідні числа будуть складеними.

Як я встигну?

Я буду буквально запускатися time ./myprogв моїй системі Ubuntu, щоб виконати терміни, тому, будь ласка, також поставте повну програму для мене для запуску, яка включає будь-яку функцію, яку ви визначили.

Примітка для складених мов

Час компіляції повинен займати не більше 1 хвилини на моїй машині.

Чи це насправді можливо?

Якщо ви ігноруєте обмеження у просторі, то кожне з них може бути враховано менше ніж за 2 секунди на моєму комп’ютері, використовуючи чистий код Python + pypy.

Отже, що таке нетривіальний алгоритм факторингу?

Алгоритм полі Полларда швидкий і підходить для гольфу. Звичайно, існує маса інших способів поділити ціле число .

Ще швидше сито квадратичне . Це здається серйозним завданням видавити це на 140 байт.

Ведучі партитури

  • SEJPM , 10 хвилин штрафу за останній тестовий випадок + 16 секунд дюйма Haskell

Отже, нам може бути дано таке число, як 2 ** 1024?
Conor O'Brien

@ ConorO'Brien Вам не дадуть нічого з більшою кількістю цифр, ніж тестові випадки.

Отже, з точки зору точності, не більше 256 біт.
Conor O'Brien

Для введення типу 4, чи має бути вихід 2чи 2, 2?
Містер Xcoder

1
@AndersKaseorg Я оновив питання після вашої пропозиції. Спасибі.

Відповіді:


9

Хаскелл, 100 97 91 89 87 72 67 Байт

Спробуйте в Інтернеті!

-3 байти завдяки @flawr
-6 байт завдяки @flawr знову
-2 байти завдяки @flawr ще раз
-2 байти завдяки оптимізованому набору параметрів
-1 байт завдяки іншому @flawrs ще раз
-14 байт завдяки вимозі щоб отримати лише один фактор
-5 байт завдяки @AndersKaseorg

f n|let s x=mod(x*x+7)n;a#b|d<-gcd(b-a)n,d>1=d|c<-s b=s a#s c=5#s 5

Це працює за перші 5 тестових випадків за непомітний час.
Ймовірно, цей час очікується на найбільшому тестовому випадку.

Загалом це, як правило, поверне один нетривіальний коефіцієнт у часі, пропорційний квадратному кореню найменшого коефіцієнта.
Він не працюватиме на кожному вході, оскільки він не варіює поліном і виявлення виняткового випадку важко зробити в 140 байтах.
Він також не виведе повну факторизацію, а скоріше нетривіальний коефіцієнт і поділ вхідного даних на цей коефіцієнт.
Він також не буде сортувати фактори за розміром.

Використовуваний метод - Поллард-Ро-Факторинг зі стандартним початковим значенням 2 (зі стандартнимx^2+1 поліномі, застосованому один раз) і нестандартним коефіцієнтом постійного многочлена 7 (оскільки 1не працював з 1679) для всіх подальших оцінок.

Повна програма ( factor.hs):

import System.Environment(getArgs)

f n|let s x=mod(x*x+7)n;a#b|d<-gcd(b-a)n,d>1=d|c<-s b=s a#s c=5#s 5

main= do
      args <- getArgs
      print$f (read $ head args :: Integer)

Складіть як $ ghc factor.hs( ghcвстановлено потреби ).
Виконати як $ ./factor <number>.

Приклад виконання:

$ ./factor 187
11

Невикористаний код:

f n=g 5 (s 5)
   where s x=mod(x*x+7)n
         g a b = if d>1 then d else g(s a)(s(s b))
               where d=gcd(b-a)n

Обчислює нетривіальний коефіцієнт, викликаючи gпочаткові значення. Поліном попередньо застосовується на 2 тут і повторно застосовується за результатом (5), щоб вхід до gпункті "де" ) завжди можна було легко використовувати для тесту gcd. g(версія для гольфу використовує інфікс #) потім намагається обчислити нетривіальний коефіцієнт d(у пункті де у версії без гольфу, в рядку в гольф) як різницю між двома входами g, якщо це вдасться, повертає вказаний фактор , ще намагається. Тут він може генеруватися nяк вихід, якщо a==bі, таким чином, повертає лише тривіальний фактор, правильним підходом до цього було б або змінити початкові значення при цій події, або змінити многочлен.


|1<2=s a#(s$s b)можна було б замінити на |c<-s b=s a#s cЯ думаю :) (також: чому ви не опублікуєте посилання на TIO ?)
недолік

Я оновив питання після пропозицій щодо коментарів. Тепер вам потрібно вивести лише один коефіцієнт, і числа гарантовано складені.

3
PS: чому ми займаємось гольфом, це навіть не код-гольф
недолік

4
Тепер у вас є 53 байти, в яких можна реалізувати ще більш складний алгоритм факторингу :)

1
Також ви можете вивезти abs , оскільки bце завжди невід’ємно. (Можливо, ти мав на увазі abs$b-a, але gcdприймає негативні аргументи і завжди дає негативний результат.) Це зводить це до менш ніж половини твіту!
Anders Kaseorg

6

Парі / GP , 137 байт, ~ 5 секунд

Використання вбудованих еліптичних операцій кривої GP (та деякої невмілої настройки параметрів) :

ecm(n)=iferr(if(n%2==0,2,n%3==0,3,for(a=1,n,ellmul(ellinit(Mod([a,a^2-a-1],n)),[1,a],lcm([1..ceil(4^a^0.5)])))),e,gcd(n,lift(Vec(e)[3])))

ecmце функція, яка (повинна) повернути фактор. Спробуйте в Інтернеті!

Тест:

ecm(n)=iferr(if(n%2==0,2,n%3==0,3,for(a=1,n,ellmul(ellinit(Mod([a,a^2-a-1],n)),[1,a],lcm([1..ceil(4^a^0.5)])))),e,gcd(n,lift(Vec(e)[3])))

{
ns = [
  187,
  1679,
  14369648346682547857,
  34747575467581863011,
  52634041113150420921061348357,
  82312263010898855308580978867,
  205255454905325730631914319249,
  1233457775854251160763811229216063007,
  1751952685614616185916001760791655006749
  ]
}

test(n) = {
    d = ecm(n);
    if (!(1<d && d<n && n%d==0), error(d));
    print(n, ": ", d)
}

apply(test, ns)

quit

Безумовно:

ecm(n) = {
  iferr(if(n%2 == 0, 2,
           n%3 == 0, 3,
           for(a = 1, n,
               /* x^3 + A*x + B = y^2 */
               E = ellinit(Mod([a, a^2-a-1], n)); /* [A, B] */
               x0 = [1, a]; /* [x, y] */
               B = ceil(4^a^0.5); /* ~ exp(sqrt(log(p))), p ~= exp(a) */
               print("a=", a, ", B=", B);
               ellmul(E, x0, lcm([1..B]))
              )
          ),
         ERR, gcd(n, lift(Vec(ERR)[3] /* = Mod(d, n) */)),
         errname(ERR)=="e_INV")
}

На жаль, для обробки факторів 2 і 3 використовується багато байтів. Байти, які могли бути використані для додавання етапу 2:

ecm(n)=iferr(for(a=1,n,Y=X=ellmul(E=ellinit(Mod([a,1],n)),[0,1],(B=ceil(4^a^0.5))!);for(z=0,9*B,Y=elladd(E,Y,X))),e,gcd(n,lift(Vec(e)[3])))

1

Аксіома, 137 байт 9 хвилин

p(n:PI):PI==(j:=1;a:=3;s:=n^.2;repeat(b:=j:=nextPrime(j);repeat(b<s=>(b:=b*j);break);a:=powmod(a,b,n);d:=gcd(a-1,n);d>1 or j>n=>break);d)

над функцією p (), яка б реалізувала al-p-1 для факторингу нижче, ніж скопіювати у файл для тестування на функцію p ()

-- one has to copy this below text in a file name for example file.input
-- in one window where there is Axiom one could write 
-- )read C:\absolutepathwherethereisthatfile\file
-- and call the function test()
-- test()
-- the first character of all function and array must be afther a new line "\n"
)cl all
)time on
vA:=[187,1679,14369648346682547857,34747575467581863011,52634041113150420921061348357,82312263010898855308580978867,205255454905325730631914319249,1233457775854251160763811229216063007, 1751952685614616185916001760791655006749]

p(n:PI):PI==(j:=1;a:=3;s:=n^.2;repeat(b:=j:=nextPrime(j);repeat(b<s=>(b:=b*j);break);a:=powmod(a,b,n);d:=gcd(a-1,n);d>1 or j>n=>break);d)

-- this would try to factor n with p-1 Pollard method
pm1(n:PI):PI==
   j:=1;a:=3;s:=n^.2
   repeat
      b:=j:=nextPrime(j)
      repeat(b<s=>(b:=b*j);break)
      a:=powmod(a,b,n)
      d:=gcd(a-1,n);d>1 or j>n=>break
   d

test()==(for i in 1..#vA repeat output [vA.i, p(vA.i)])

результати тут:

(5) -> test()
   [187,11]
   [1679,73]
   [14369648346682547857,9576890767]
   [34747575467581863011,9576890767]
   [52634041113150420921061348357,2860486313]
   [82312263010898855308580978867,311111111111113]
   [205255454905325730631914319249,2860486313]
   [1233457775854251160763811229216063007,1111111999999]
   [1751952685614616185916001760791655006749,36413321723440003717]
                                                               Type: Void
                              Time: 496.78 (EV) + 53.05 (GC) = 549.83 sec

Не могли б ви точно прописати, як запустити цей код з командного рядка в ubuntu? Я встановив аксіому і створив файл під назвою foo.ax з вашим кодом, який не використовується для гольфу.

@Lembik 1) перейменувати fop.ax у foo.input 2) запустити Axiom в одному терміналі або xterm 3) записати в цей термін Axiom наступну команду ") read C: Absolpath \ foo" 4) написати в термінал Axiom call функціонувати тест (). Так робити в Windows, підказки мені здається відкрити одну сесію Axiom і завантажити файл командою ") read"
RosLuP

@ Лембік, якщо є проблеми з файлами, я думаю, це теж було б нормально: 1) запустити Аксіому 2) написати) час на <return> в програмі Axiom 3) скопіювати пасту і натиснути повернення у кожній "копіювальній пасті" в програмі Axiom: масив vA, функція p () та test () 4) в програмі Axiom test test () <return>
RosLuP

@ Лембік, так що часу потрібно?
RosLuP

1

Аксіома, 10 хвилин + 31 секунда

A(a)==>a:=(a*a+7)rem n;z(n)==(p:=a:=b:=101;for i in 1..repeat(A(a);A(b);A(b);p:=mulmod(p,a-b,n);i rem 999<9=>(p:=gcd(p,n);p>1=>break));p)

z () - функція rho, одна функція 137 байт; ungolfed z () і називати його як rho (). Можна припустити, що gcd (0, n) = n, тому цикл зупиняється і повертається для відмови n.

)time on    
rho(n)==
  p:=a:=b:=101
  for i in 1..repeat
          A(a);A(b);A(b)
          p:=mulmod(p,a-b,n)
          i rem 999<9=>(p:=gcd(p,n);p>1=>break)
  p

va1:=[187,1679,14369648346682547857,34747575467581863011,52634041113150420921061348357,82312263010898855308580978867,205255454905325730631914319249,1233457775854251160763811229216063007, 1751952685614616185916001760791655006749]
p1()==(for i in 1..#va1-1 repeat output [va1.i,z(va1.i)]) 

результати (z () добре для всіх, але останнє число 1751952685614616185916001760791655006749 залишається не врахованим (10 хвилин))

(6) -> p1()
   [187,17]
   [1679,23]
   [14369648346682547857,1500450271]
   [34747575467581863011,3628273133]
   [52634041113150420921061348357,2860486313]
   [82312263010898855308580978867,264575131106459]
   [205255454905325730631914319249,2860486313]
   [1233457775854251160763811229216063007,1111111999999]
                                                               Type: Void
                                 Time: 30.38 (EV) + 1.38 (GC) = 31.77 sec

(8) -> z(1679)
   (8)  23
                                                    Type: PositiveInteger
                                                              Time: 0 sec

0

Python 3 , 100 99 байт, 45 40 39 секунд + 10 хвилин штрафу

import math
def f(n):
 x=y=2;d=1
 while d<2:y=y*y+1;x,y=1+x*x%n,y*y%n+1;d=math.gcd(x-y,n)
 return d

Спробуйте в Інтернеті!

Використовує Поллард-Ро з початковим значенням 2 та многочленом x ^ 2 + 1.


Ви можете використовувати pow(за допомогою 3-го аргументу) для покращення швидкості виконання.
mbomb007
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.