Знайдіть основні фактори


23

У цьому завданні ви повинні написати програму, яка обчислює прості множники числа. Вхід - натуральне число 1 <n <2 ^ 32. Вихід - це список простих факторів числа у наступному форматі. Експоненти повинні бути опущені, якщо вони є 1. Лише вихідні прості числа. (Припустимо, що вхід становить 131784):

131784 = 2 ^ 3 * 3 * 17 ^ 2 * 19

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


9
Бонусні бали, якщо ваша програма може враховувати 6857599914349403977654744967172758179904114264612947326127169976133296980951450542789808884504301075550786464802304019795402754670660318614966266413770127!
Джої Адамс

@Joey Adams: факторизація починається з 17 * 71 * 113 * 997 * 313597 ...
FUZxxl

3
@FUZxxl: Я думаю, ви помилилися скопіювавши номер. Це твір двох великих прайменів .
Джої Адамс

@Joey Чи можемо ми використовувати алгоритм Шор?
Матін Ульхак

23
@Joey Я випадково пролив каву по моєму квантовому комп'ютеру, і мій друг використовує його, щоб "зламати уряд США" або щось неважливо, так, ні. :(
Mateen Ulhaq

Відповіді:


11

SageMath, 31 байт

N=input()
print N,"=",factor(N)

Тестовий випадок: 83891573479027823458394579234582347590825792034579235923475902312344444 Виходи:

83891573479027823458394579234582347590825792034579235923475902312344444 = 2^2 * 3^2 * 89395597 * 98966790508447596609239 * 263396636003096040031295425789508274613


Вітаю вас за те, що виграли виклик своїм першим постом, приємна робота! І ласкаво просимо на сайт!
DJMcMayhem

8

Рубін 1,9, 74 70 символів

#!ruby -plrmathn
$_+=?=+$_.to_i.prime_division.map{|a|a[0,a[1]]*?^}*?*

Зміни:

  • (74 -> 70) Просто використовуйте експонент як довжину зрізу, а не чітко перевіряючи exponent > 1

7

Perl 5.10, 73 88

perl -pe '$_=`factor $_`;s%( \d+)\K\1+%-1-length($&)/length$1%ge;y, -,*^,;s;\D+;=;'

Приймає номер введення зі стандартного вводу. Вирахує коефіцієнти для декількох входів, якщо вони надані.

Розраховується як різниця до perl -e. 5.10 потрібно для \Kметахарактера регулярних виразів.


+1 для використання factor.
st0le

Чи не слід розраховувати pваріант?
Joey

@Joey справді я повинен. Вибач за це. Закріплення.
JB

Ви цього не перевіряли, але замість цього split/\D/,~factor $_~;$_="@_";можете написати $_=~factor $_~;s/\D/ /g;? (Звичайно, замініть ~на backtick.)
Timwi

Ви маєте на увазі $_=`factor $_`;s/\D/ /g;? Подвійне кодування зворотного зв'язку допомагає
aaaaaaaaaaaa

5

OCaml, 201 символів

Прямий імперативний переклад найкращого коду Python:

let(%)s d=if!d>1then Printf.printf"%s%d"s!d
let f n=let x,d,e,s=ref n,ref 1,ref 0,ref"="in""%x;while!d<65536do
incr d;e:=0;while!x mod!d=0do x:=!x/ !d;incr e
done;if!e>0then(!s%d;"^"%e;s:="*")done;!s%x

Наприклад,

# f 4294967292;;
4294967292=2^2*3^2*7*11*31*151*331- : unit = ()

(зауважте, я випустив остаточну кінцеву лінію.) Просто для розваги, на 213 символів, чисто функціональна версія, ретельно затуманена через ліберальне використання операторів:

let(%)s d=if d>1then Printf.printf"%s%d"s d
let f x=let s=ref"="in""%x;let rec(@)x d=if d=65536then!s%x else
let rec(^)x e=if x/d*d<x then x,e else x/d^e+1in
let x,e=x^0in if e>0then(!s%d;"^"%e;s:="*");x@d+1in x@2

5

Пітон, 140 135 133 символів

M=N=input()
s=''
f=1
while f<4**8:
 f+=1;e=0
 while N%f<1:e+=1;N/=f
 if e:s+='*%d'%f+'^%d'%e*(e>1)
print M,'=',(s+'*%d'%N*(N>1))[1:]

Я думаю, що для виходу потрібні ще місця, наприклад ' * %d'... І ще дві речі 65536 == 4**8:; 7 рядок:if e:s+='*%d'%f+'^%d'%e*(e>1)
Олег Припін

@BlaXpirit: "стільки пробілів не потрібно". Дякую двом іншим, я їх включу.
Кіт Рендалл

5

J, 72

(":*/f),'=',([,'*',])/(":"0~.f),.(('^',":)`(''"0)@.(=&1))"0+/(=/~.)f=.q:161784

Типовий J. Два персонажі, які роблять більшу частину роботи, шістдесят символів, щоб представити його.

Редагувати: виправлено кількість символів.


2
Мені це не схоже на 62 символи. Навіть якщо вважати, що 161784це ваш внесок, це все ще 72 символи.
Вентеро

Чи не було б коротше |: __ q: y?
Енадцять

2
@ Вентеро: типовий JB. Дві години, щоб грати в прокляту річ, п'ятнадцять секунд, щоб зіпсувати кількість персонажів.
JB

5

J, 53 52 символи

Це рішення сприймає rplcхитрість з рішення випадкових, але також пропонує деякі оригінальні ідеї.

":,'=',(":@{.,'^','*',~":@#)/.~@q:}:@rplc'^1*';'*'"_

У негласних позначеннях ця функція стає

f =: 3 : 0
(": y) , '=' , }: (g/.~ q: y) rplc '^1*' ; '*'
)

де gвизначено як

g =: 3 : 0
": {. y) , '^' , (": # y) , '*'
)
  • q: yє вектором головних чинників в y. Наприклад, q: 60урожайність 2 2 3 5.
  • x u/. yзастосовується uдо y keyed by x, тобто uзастосовується до векторів елементів, yдля яких записи в xних рівні. Це трохи складно пояснити, але в окремому випадку , y u/. yабо u/.~ y, uзастосовується до кожного вектору різних елементів y, де кожен елемент повторюється для так часто , як він з'являється в y. Наприклад, </.~ 1 2 1 2 3 1 2 2 3урожайність

    ┌─────┬───────┬───┐
    │1 1 1│2 2 2 2│3 3│
    └─────┴───────┴───┘
    
  • # yце число з y, тобто, кількість елементів y.

  • ": y формати y як рядок.
  • x , y додає x і y.
  • {. yце голова y , тобто її перший пункт.
  • Таким чином, (": {. y), '^' , (": # y) , '*'формується вектор n повторень числа k у рядок форми k ^ n *. Це словосполучення в мовчазних позначеннях :@{.,'^','*',~":@#, яке ми передаємо /.описаному вище прислівнику .
  • x rplc yце функція бібліотеки заміни символів. yмає форму a ; bі кожен екземпляр рядка aв xзамінюється на b. xрозгортається (тобто переробляється таким чином, щоб він мав ранг 1) перед початком роботи, яка тут використовується. Цей код замінює ^1*з , *як виконати дорученої формат виведення.
  • }: yє Позбавляти з y, тобто все , але його останній елемент. Це використовується для вилучення останнього *.

Не вдалося заощадити багато роботи, використовуючи __ q:? Спробуйте в Інтернеті!
Адам

@ Adám Дійсно, гарна ідея!
FUZxxl

4

PHP, 112

echo$n=$_GET[0],'=';$c=0;for($i=2;;){if($n%$i<1){$c++;$n/=$i;}else{if($c){echo"$i^$c*";}$c=0;if(++$i>$n)break;}}

118

echo $n=$_GET[0],'=';for($i=2;;){if(!($n%$i)){++$a[$i];$n/=$i;}else{if($a[$i])echo "$i^$a[$i]*";$i++;if($i>$n)break;}}

3

Python 119 Chars

M=N=input()
i=1
s=""
while N>1:
 i+=1;c=0
 while N%i<1:c+=1;N/=i
 if c:s+=" * %d"%i+['','^%d'%c][c>1]
print M,'=',s[3:]

1
Це я спробував спочатку, але це занадто повільно для великих праймерів, як, наприклад, 4294967291.
Кіт Рендалл,

@Keith Питання дозволяє тривати до 10 хвилин. Це займе більше ніж 10 хвилин для найгіршого випадку?
fR0DDY

2
На цю машину на це число пішло 32 хвилини.
Кіт Рендалл

3

JavaScript, 124 122 119

for(s='',i=2,o=p=prompt();i<o;i++){for(n=0;!(p%i);n++)p/=i;n?s+=i+(n-1?'^'+n:'')+'*':0}alert(s.substring(0,s.length-1))

3

Перл, 78

use ntheory":all";say join" * ",map{(join"^",@$_)=~s/\^1$//r}factor_exp(shift)

Він використовує s /// r функцію Perl 5.14 для усунення ^ 1s. 81 символ для запуску в циклі:

perl -Mntheory=:all -nE 'chomp;say join" * ",map{(join"^",@$_)=~s/\^1$//r}factor_exp($_);'

Ви можете залишити пробіли, якщо хочете. Це врятувало б двох символів. Приємне рішення!
FUZxxl

2

PHP, 236 символів

$f[$n=$c=$argv[1]]++;echo"$n=";while($c){$c=0;foreach($f as$k=>$n)for($r=~~($k/2);$r>1;$r--){if($k%$r==0){unset($f[$k]);$f[$r]++;$f[$k/$r]++;$c=1;break;}}}foreach($f as$k=>$n)if(--$n)$f[$k]="$k^".++$n;else$f[$k]=$k;echo implode("*",$f);

Вихід для 131784: 2 ^ 3 * 3 * 17 ^ 2 * 19

Виконує всі номери протягом декількох секунд під час тестування.

4294967296=2^32
Time: 0.000168

Введення ніколи не було вказано, тому я вирішив викликати його за допомогою аргументів командного рядка.

php factorize.php 4294967296

2

Scala 374:

def f(i:Int,c:Int=2):List[Int]=if(i==c)List(i)else 
if(i%c==0)c::f(i/c,c)else f(i,c+1)
val r=f(readInt)
class A(val v:Int,val c:Int,val l:List[(Int,Int)])
def g(a:A,i:Int)=if(a.v==i)new A(a.v,a.c+1,a.l)else new A(i,1,(a.v,a.c)::a.l)
val a=(new A(r.head,1,Nil:List[(Int,Int)])/:(r.tail:+0))((a,i)=>g(a,i))
a.l.map(p=>if(p._2==1)p._1 else p._1+"^"+p._2).mkString("", "*", "")

неозорений:

def factorize (i: Int, c: Int = 2) : List [Int] = {
  if (i == c) List (i) else 
    if (i % c == 0) c :: f (i/c, c) else 
      f (i, c+1)
}
val r = factorize (readInt)
class A (val value: Int, val count: Int, val list: List [(Int, Int)])
def g (a: A, i: Int) = 
  if (a.value == i) 
    new A (a.value, a.count + 1, a.list) else 
    new A (i, 1, (a.value, a.count) :: a.list)
val a = (new A (r.head, 1, Nil: List[(Int,Int)]) /: (r.tail :+ 0)) ((a, i) => g (a, i))
a.l.map (p => if (p._2 == 1) p._1 else
  p._1 + "^" + p._2).mkString ("", "*", "")

2

J, 74 символів

f=.3 :0
(":y),'=',' '-.~('^1 ';'')rplc~}:,,&' *'"1(,'^'&,)&":/"{|:__ q:y
)

   f 131784
131784=2^3*3*17^2*19

64 символи з введенням у змінну x:

   x=.131784

   (":x),'=',' '-.~('^1 ';'')rplc~}:,,&' *'"1(,'^'&,)&":/"{|:__ q:x
131784=2^3*3*17^2*19

Якщо вам вдасться перетворити це на мовчазне визначення, ви можете уникати всіх цитат. Ви також можете використовувати визначення 3 : 0.
FUZxxl

@FUZxxl Я очікував, що я можу просто вставити нерозміщену рядок у 3 : 0версії, але вона не працює. Можливо, я спробую пізніше спробувати. Це 3: 0 я спробував: pastebin.com/rmTVAk4j .
randomra

Це має працювати. Я не бачу чому. Ви назвали свій аргумент так, yяк вам належить?
FUZxxl

@FUZxxl Це 3: 0 я спробував: pastebin.com/rmTVAk4j .
Випадкова

Спробуваний вами 3: 0 точно не відповідає тому, який ви надали. Він використовується ''замість a:одного місця. Може, в цьому різниця?
FUZxxl

2

Java 10, 109 108 байт (лямбда-функція) (неконкурентова на запит ОП)

n->{var r=n+"=";for(int i=1,f;i++<n;r+=f<1?"":(f<2?i:i+"^"+f)+(n>1?"*":""))for(f=0;n%i<1;n/=i)f++;return r;}

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

Java 6+, 181 байт (повна програма)

class M{public static void main(String[]a){long n=new Long(a[0]),i=1,f;String r=n+"=";for(;i++<n;r+=f<1?"":(f<2?i:i+"^"+f)+(n>1?"*":""))for(f=0;n%i<1;n/=i)f++;System.out.print(r);}}

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

-1 байт завдяки @ceilingcat .

Пояснення:

n->{                // Method with integer parameter and String return-type
  var r=n+"=";      //  Result-String, starting at the input with an appended "="
  for(int i=1,f;i++<n;
                    //  Loop in the range [2, n]
      r+=           //    After every iteration: append the following to the result-String:
        f<1?        //     If the factor `f` is 0:
         ""         //      Append nothing
        :           //     Else:
         (f<2?      //      If the factor `f` is 1:
           i        //       Append the current prime `i`
          :         //      Else:
           i+"^"+f) //       Append the current prime `i` with it's factor `f`
         +(n>1?     //      And if we're not done yet:
            "*"     //       Also append a "*"
           :        //      Else:
            ""))    //       Append nothing more
    for(f=0;        //   Reset the factor `f` to 0
        n%i<1;      //   Loop as long as `n` is divisible by `i`
      n/=i)         //    Divide `n` by `i`
      f++;          //    Increase the factor `f` by 1
  return r;}        //  Return the result-String

@ceilingcat Дякую!
Кевін Круїссен

Дискваліфікована як Java 10 була створена після публікації цього завдання.
FUZxxl

@FUZxxl Я позначив лямбду Java 10 як неконкурентну і додав програму Java 6, яка була випущена в грудні 2006 року .
Кевін Круїссен

Гаразд, круто. Це працює для мене!
FUZxxl

2

Japt , 28 27 26 байт

-1 байт завдяки Шаггі

+'=+Uk ü ®ÊÉ?ZÌ+'^+Zl:ZÃq*

Спробуй це


Дискваліфіковано, оскільки ваша мова була створена після публікації цього завдання.
FUZxxl


Це не було дозволено, коли виклик було розміщено. Я вважаю несправедливим змінити правила оскарження після опублікування виклику, тому мови, опубліковані після цього виклику, залишаються незаконними.
FUZxxl

1
@FUZxxl Не потрібно приймати мою відповідь, але мені дозволяють відповісти на неї незалежно.
Олівер


1

Powershell, 113 97 байт

Натхненний Джої відповідь . Це повільно, але коротко.

param($x)(2..$x|%{for(;!($x%$_)){$_
$x/=$_}}|group|%{$_.Name+"^"+$_.Count-replace'\^1$'})-join'*'

Пояснений тестовий сценарій:

$f = {

param($x)               # let $x stores a input number > 0
(2..$x|%{               # loop from 2 to initial input number
    for(;!($x%$_)){     # loop while remainder is 0
        $_              # push a current value to a pipe
        $x/=$_          # let $x is $x/$_ (new $x uses in for condition only)
    }
}|group|%{              # group all values
    $_.Name+"^"+$_.Count-replace'\^1$'  # format and remove last ^1
})-join'*'              # make string with *

}

&$f 2
&$f 126
&$f 129
&$f 86240
#&$f 7775460

Вихід:

2
2*3^2*7
3*43
2^5*5*7^2*11

1

Желе , 16 байт (не змагається на запит ОП)

³”=³ÆFḟ€1j€”^j”*

Один із моїх перших відповідей на Jelly, тому точно можна пограти в гольф (особливо ³”=³).

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

Пояснення:

³                 # Push the first argument
 ”=               # Push string "="
   ³ÆF            # Get the prime factor-exponent pairs of the first argument
      ḟ€1         # Remove all 1s from each pair
         j€”^     # Join each pair by "^"
             j”*  # Join the pair of strings by "*"
                  # (implicitly join the entire 'stack' together)
                  # (which is output implicitly as result)

Дискваліфіковано, оскільки ваша мова була створена після публікації цього завдання.
FUZxxl

@FUZxxl З середини 2017 року неконкурентоспроможність більше не є мета , якщо виклик прямо не говорить про те, що мови повинні бути старшими за час публікації. Але якщо ви як той, хто опублікував виклик, вирішив забороняти мови, новіші за дату виклику, я відредагую свої відповіді, щоб додати явну (non-competing). :)
Кевін Круїссен

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

@FUZxxl Я вказав свої відповіді як неконкурентоспроможні, як вимагали.
Кевін Круїссен

Дякую за твою допомогу.
FUZxxl

1

05AB1E , 22 20 байт (не змагається на запит ОП)

ÐfsÓ0Køε1K'^ý}'*ý'=ý

-2 байти завдяки @Emigna .

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

Пояснення:

Ð                # Triplicate the (implicit) input-integer
 f               # Pop and push all prime factors (without counting duplicates)
  s              # Swap to take the input again
   Ó             # Get all prime exponents
    0K           # Remove all 0s from the exponents list
      ø          # Zip it with the prime factors, creating pairs
       ε         # Map each pair to:
        1K       #  Remove all 1s from the pair
        '^ý     '#  And then join by "^"
       }'*ý     '# After the map: join the string/integers by "*"
           '=ý  '# And join the stack by "=" (with the input we triplicated at the start)
                 # (after which the result is output implicitly)

1Kмає працювати замість `≠ iy у циклі.
Емінья

@Emigna А-а-а-а-а, я, власне, це роблю у своїй відповіді на желе, яку я щойно розмістив . Не впевнений, чому я не думав про це раніше тут. :)
Кевін Круїссен

Дискваліфіковано, оскільки ваша мова була створена після публікації цього завдання.
FUZxxl

1

APL (NARS), 66 символів, 132 байти

{(⍕⍵),'=',3↓∊{m←' * ',⍕↑⍵⋄1=w←2⊃⍵:m⋄m,'^',⍕w}¨v,¨+/¨{k=⍵}¨v←∪k←π⍵}

тест та коментар:

  f←{(⍕⍵),'=',3↓∊{m←' * ',⍕↑⍵⋄1=w←2⊃⍵:m⋄m,'^',⍕w}¨v,¨+/¨{k=⍵}¨v←∪k←π⍵}
  f 131784
131784=2^3 * 3 * 17^2 * 19
  f 2
2=2
  f (2*32)
4294967296=2^32

{(⍕⍵),'=',3↓∊{m←' * ',⍕↑⍵⋄1=w←2⊃⍵:m⋄m,'^',⍕w}¨v,¨+/¨{k=⍵}¨v←∪k←π⍵}
k←π⍵      find the factors with repetition of ⍵ and assign that array to k example for 12 k is 2 2 3
v←∪       gets from k unique elements and put them in array v
+/¨{k=⍵}¨ for each element of v count how many time it appear in k (it is array exponents)
v,¨       make array of couples from element of v (factors unique) and the array above (exponents unique)
∊{m←' * ',⍕↑⍵⋄1=w←2⊃⍵:m⋄m,'^',⍕w}¨ pretty print the array of couples factor exponent as array chars
3↓                                 but not the first 3 chars
(⍕⍵),'='  but print first the argument and '=' in char format

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


0

JavaScript, 107

n=prompt()
s=n+'='
c=0
for(i=2;;){if(n%i<1){c++
n/=i}else{if(c)s+=i+'^'+c+'*'
c=0
if(++i>n)break}}
alert(s)

120

n=prompt()
o={2:0}
for(i=2,c=n;i<=c;)!(c%i)?++o[i]?c/=i:0:o[++i]=0
s=n+'='
for(i in o)s+=o[i]?i+'^'+o[i]+'*':''
alert(s)

1
Має кінцевий *висновок і друкує показник, навіть якщо це 1.
Вентеро,

не потрібно брати участь у голосуванні. Ніде не сказано, що він не може надрукувати показник, якщо він 1. Також, трейлінг *передбачає множення на 1. Якщо це велике питання, я його виправлю.
zzzzBov

1
"У наступному форматі" в описі завдання в значній мірі означає, що показник 1не повинен бути надрукований. І ні, заперечення *теж проти цього. Якби можна було вільно вибрати вихідний формат, тоді обстріл був factor(1)би найпростішим. Відповіді можна порівняно лише порівняти, якщо всі вони вирішують ту саму проблему.
Джої

3
Як творець цього завдання, я кажу, що експоненти повинні бути пропущені, якщо 1 і тільки прості числа можуть бути чинниками.
FUZxxl


0

PHP, 93 байти

<?=$n=$argn;for($i=2;$n>1;$k&&$p=print($p?"*":"=")."$i^$k",$i++)for($k=0;$n%$i<1;$n/=$i)$k++;

Я міг зробити 89 байт з PHP 5.5 (або пізнішої версії), але це вирішує проблему більш ніж на 2 роки:

<?=$n=$argn;for($i=2;$n>1;$k&&$p=print"=*"[$p]."$i^$k",$i++)for($k=0;$n%$i<1;$n/=$i)$k++;

Запустіть як трубу -nFабо спробуйте їх в Інтернеті .

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