Znajdź czynniki pierwsze


23

W tym zadaniu musisz napisać program, który oblicza czynniki pierwsze liczby. Dane wejściowe to liczba naturalna 1 <n <2 ^ 32. Dane wyjściowe to lista głównych czynników liczby w następującym formacie. Wykładniki należy pominąć, jeśli są 1. Wyprowadzają tylko liczby pierwsze. (Zakładając, że dane wejściowe to 131784):

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

Korzystanie z tej samej ilości białych znaków nie jest wymagane; w miarę potrzeby można wstawić spację. Twój program powinien zakończyć się w mniej niż 10 minut dla każdego wejścia. Wygrywa program z najkrótszą liczbą znaków.


9
Punkty bonusowe, jeśli Twój program może uwzględniać 6857599914349403977654744967172758179904114264612947326127169976133296980951450542789808884504301075550786464802304019795402754670660318614966266413770127!
Joey Adams,

@Joey Adams: Rozkład na czynniki pierwsze zaczyna się od 17 * 71 * 113 * 997 * 313597 ...
FUZxxl

3
@FUZxxl: Myślę, że popełniłeś błąd podczas kopiowania numeru. Jest to iloczyn dwóch dużych liczb pierwszych .
Joey Adams,

@Joey Czy możemy użyć algorytmu Shora?
Mateen Ulhaq

23
@Joey Przypadkowo rozlałem kawę na mój komputer kwantowy, a mój przyjaciel używa go do „włamania się do rządu USA” lub czegoś nieistotnego, więc nie. :(
Mateen Ulhaq

Odpowiedzi:


11

SageMath, 31 bajtów

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

Przypadek testowy: wyniki 83891573479027823458394579234582347590825792034579235923475902312344444 :

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


Gratulujemy wygrania wyzwania swoim pierwszym postem, fajna robota! Witamy na stronie!
DJMcMayhem

8

Ruby 1.9, 74 70 znaków

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

Edycje:

  • (74 -> 70) Wystarczy użyć wykładnika jako długości plasterka zamiast jawnego sprawdzania exponent > 1

7

Perl 5.10, 73 88

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

Pobiera numer wejścia ze standardowego wejścia. Oblicza współczynniki dla wielu danych wejściowych, jeśli są podane.

Liczone jako różnica do perl -e. 5.10 jest potrzebne dla \Kmetaznaku wyrażenia regularnego.


+1 za użycie factor.
st0le,

Nie powinieneś liczyć popcji?
Joey,

@Joey rzeczywiście powinienem. Przepraszam za to. Ustalenie.
JB

Nie przetestowałem tego, ale zamiast split/\D/,~factor $_~;$_="@_";pisać $_=~factor $_~;s/\D/ /g;? (Oczywiście zamień ~na backtick.)
Timwi

Masz na myśli $_=`factor $_`;s/\D/ /g;? Pomaga podwójna obudowa wsteczna.
aaaaaaaaaaaa

5

OCaml, 201 znaków

Bezpośrednie tłumaczenie imperatywnego najlepszego kodu w języku 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

Na przykład,

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

(zauważ, że pominąłem wypisywanie końcowego punktu końcowego). Dla zabawy, przy 213 znakach, wersja czysto funkcjonalna, całkowicie zaciemniona przez swobodne użycie operatorów:

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

Python, 140 135 133 znaków

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:]

Myślę, że wyjście wymaga więcej spacji, np. ' * %d'... I jeszcze dwie rzeczy 65536 == 4**8:; Linia 7:if e:s+='*%d'%f+'^%d'%e*(e>1)
Oleh Prypin

@BlaXpirit: „ta sama ilość białych znaków nie jest wymagana”. Dzięki za pozostałe dwa, włączę je.
Keith Randall,

5

J, 72

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

Typowy J. Dwie postacie do wykonania większości pracy, sześćdziesiąt postaci do przedstawienia.

Edycja: Naprawiono liczbę znaków.


2
Nie wygląda mi to na 62 znaków. Nawet przy założeniu, że 161784jest to twój wkład, nadal ma 72 znaki.
Ventero

Czy nie byłoby to krótsze |: __ q: y?
Eelvex

2
@Ventero: typowy JB. Dwie godziny gry w golfa, piętnaście sekund na zepsucie liczby postaci.
JB

5

J, 53 52 znaki

To rozwiązanie bierze rplcsztuczkę z rozwiązania randomra, ale zawiera też kilka oryginalnych pomysłów.

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

W notacji niejawnej ta funkcja staje się

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

gdzie gjest zdefiniowane jako

g =: 3 : 0
": {. y) , '^' , (": # y) , '*'
)
  • q: yjest wektorem czynniki pierwsze o y. Na przykład q: 60daje 2 2 3 5.
  • x u/. ystosuje się udo y keyed przez x, to uznaczy stosuje się do wektorów elementów, ydla których wpisy xsą równe. To jest trochę skomplikowane, aby wyjaśnić, a w szczególnym przypadku y u/. ylub u/.~ y, ustosuje się do każdego wektora odrębnych elementów y, w których każdy element jest powtarzany tak często, jak to pojawia się y. Na przykład </.~ 1 2 1 2 3 1 2 2 3daje

    ┌─────┬───────┬───┐
    │1 1 1│2 2 2 2│3 3│
    └─────┴───────┴───┘
    
  • # yjest tally of y, czyli liczba elementów w y.

  • ": y formaty y jako ciąg.
  • x , y dołącza x i y.
  • {. yjest głową y , czyli jej pierwszym przedmiotem.
  • W ten sposób (": {. y), '^' , (": # y) , '*'formatuje wektor n powtórzeń liczby k na ciąg postaci k ^ n *. To wyrażenie w milczącej notacji to :@{.,'^','*',~":@#, które przekazujemy do przysłówka /.opisanego powyżej.
  • x rplc yto funkcja biblioteczna zastępująca znaki. yma kształt a ; bi każde wystąpienie łańcucha aw xzastępuje b. xjest zniszczony (to znaczy przekształcony tak, że ma rangę 1) przed rozpoczęciem operacji, która jest tutaj używana. Ten kod zastępuje ^1*się znakiem *zgodności z obowiązującym formatem wyjściowym.
  • }: yjest ograniczyć z y, czyli wszystko, ale jego ostatni element. Służy do usuwania końcowego *.

Czy nie możesz zaoszczędzić dużo pracy, używając __ q:? Wypróbuj online!
Adám

@ Adám Rzeczywiście, dobry pomysł!
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 znaków

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
Właśnie tego próbowałem najpierw, ale jest zbyt wolny dla dużych liczb pierwszych, np. 4294967291.
Keith Randall

@ Keith Pytanie pozwala na maksymalnie 10 minut. Czy w najgorszym przypadku zajmie to więcej niż 10 minut?
fR0DDY,

2
Numer ten zajął na moim komputerze 32 minuty.
Keith Randall,

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

Perl, 78

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

Używa funkcji s /// r Perla 5.14, aby uniknąć ^ 1s. 81 znaków do uruchomienia w pętli:

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

Jeśli chcesz, możesz pominąć spacje. Uratowałoby to dwie postacie. Fajne rozwiązanie!
FUZxxl,

2

PHP, 236 znaków

$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);

Wyjście dla 131784: 2 ^ 3 * 3 * 17 ^ 2 * 19

Wypełnia wszystkie liczby w ciągu kilku sekund podczas testowania.

4294967296=2^32
Time: 0.000168

Dane wejściowe nigdy nie zostały określone, dlatego zdecydowałem się wywołać je przy użyciu argumentów wiersza poleceń.

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("", "*", "")

bez golfa:

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 znaki

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

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

64 znaki z wejściem w zmiennej x:

   x=.131784

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

Jeśli uda Ci się przekształcić to w milczącą definicję, możesz uniknąć ucieczki od wszystkich cytatów. Możesz także użyć 3 : 0definicji.
FUZxxl

@FUZxxl Spodziewałem się, że mogę po prostu wstawić nieprzetworzony ciąg w 3 : 0wersji, ale to nie działało trochę. Może jednak spróbuję milczeć później. To jest 3: 0 próbowałem: pastebin.com/rmTVAk4j .
randomra

To powinno działać. Nie rozumiem dlaczego. Czy nazwałeś swój argument ytak, jak powinien?
FUZxxl

@FUZxxl To jest 3: 0 próbowałem: pastebin.com/rmTVAk4j .
randomra

Wypróbowany 3: 0 nie pasuje dokładnie do tego, który udostępniasz. Używa ''zamiast a:w jednym miejscu. Może to różnica?
FUZxxl,

2

Java 10, 109 108 bajtów (funkcja lambda) (nie konkuruje na żądanie OP)

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;}

Wypróbuj online.

Java 6+, 181 bajtów (pełny program)

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);}}

Wypróbuj online.

-1 bajt dzięki @ceilingcat .

Wyjaśnienie:

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 Thanks!
Kevin Cruijssen

Dyskwalifikacja jako Java 10 została utworzona po opublikowaniu tego zadania.
FUZxxl

@FUZxxl Oznacziłem lambda Java 10 jako niekonkurującego i dodałem program Java 6, który został wydany w grudniu 2006 roku .
Kevin Cruijssen

Ok spoko. To działa dla mnie!
FUZxxl

2

Japt , 28 27 26 bajtów

-1 bajt dzięki Shaggy

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

Spróbuj


Zdyskwalifikowany, ponieważ Twój język został utworzony po opublikowaniu tego zadania.
FUZxxl


Po opublikowaniu wyzwania nie było dozwolone. Uważam, że niesprawiedliwe jest zmienianie zasad konkursu po opublikowaniu konkursu, więc języki opublikowane po tym konkursie pozostają nielegalne.
FUZxxl

1
@FUZxxl Nie musisz akceptować mojej odpowiedzi, ale wolno mi odpowiedzieć niezależnie od tego.
Oliver


1

PowerShell, 113 97 bajtów

Zainspirowany Joey'a odpowiedź . Jest wolny, ale krótki.

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

Wyjaśniony skrypt testowy:

$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

Wydajność:

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

1

Galaretka , 16 bajtów (nie konkuruje na życzenie OP)

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

Jedna z moich pierwszych odpowiedzi na żelki, więc zdecydowanie można grać w golfa (szczególnie ³”=³) ..

Wypróbuj online.

Wyjaśnienie:

³                 # 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)

Zdyskwalifikowany, ponieważ Twój język został utworzony po opublikowaniu tego zadania.
FUZxxl

@FUZxxl Od połowy 2017 r. Niekonkurowanie nie znajduje się już w meta , chyba że wyzwanie wyraźnie stanowi, że języki powinny być starsze niż czas opublikowania. Ale jeśli Ty, jako ten, który opublikował wyzwanie, zdecydujesz się nie zezwalać na języki nowsze niż Twoje wyzwanie po dacie, zmodyfikuję moje odpowiedzi, aby dodać wyraźne (non-competing). :)
Kevin Cruijssen

Uważam, że konsensus witryny, który obowiązywał w momencie opublikowania tego wyzwania, powinien określać zasady udzielania odpowiedzi. Wszystko inne (tj. Zasady, które zmieniają się po opublikowaniu wyzwania) byłoby niesprawiedliwe. Proszę zaznaczyć swoje odpowiedzi jako niekonkurencyjne.
FUZxxl

@FUZxxl Oznacziłem swoje odpowiedzi jako niekonkurencyjne, zgodnie z żądaniem.
Kevin Cruijssen

Dziękuję za pomoc
FUZxxl

1

05AB1E , 22 20 bajtów (nie konkuruje na wniosek OP)

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

-2 bajty dzięki @Emigna .

Wypróbuj online.

Wyjaśnienie:

Ð                # 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)

1Kpowinien działać zamiast ≠ iy w pętli.
Emigna

@Emigna Ah lol .. Właściwie to robię w mojej odpowiedzi na galaretkę, którą właśnie opublikowałem . Nie jestem pewien, dlaczego wcześniej o tym nie pomyślałem. :)
Kevin Cruijssen

Zdyskwalifikowany, ponieważ Twój język został utworzony po opublikowaniu tego zadania.
FUZxxl

1

APL (NARS), 66 znaków, 132 bajty

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

przetestuj i skomentuj:

  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

jeśli ktoś ma wiele czasu z tymi prymitywami, zna je bardzo dobrze, dla mnie możliwe jest, że kod jest wyraźniejszy od komentarzy ... więc kod jest bardziej przejrzysty niż komentarze, komentarze nieprzydatne ...


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
Ma końcowy *wynik i drukuje wykładnik wykładniczy, nawet jeśli
Ventero

nie trzeba głosować. Nigdzie nie było powiedziane, że nie może wydrukować wykładnika wykładniczego, jeśli jest on równy 1. Również trailing *zakłada mnożenie 1. Jeśli to tak duży problem, naprawię to.
zzzzBov,

1
»W następującym formacie« w opisie zadania sugeruje, że wykładnik wykładnika 1nie powinien być drukowany. I nie, ciągnięcie *również jest temu przeciwne. Gdyby można swobodnie wybrać format wyjściowy, wówczas factor(1)najłatwiej byłoby go wykonać. Odpowiedzi można rozsądnie porównać tylko wtedy, gdy wszystkie rozwiązują ten sam problem.
Joey,

3
Jako twórca tego zadania, powiadam, że wykładniki należy pominąć, jeśli 1 i tylko liczby pierwsze mogą być czynnikami.
FUZxxl


0

PHP, 93 bajty

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

Mógłbym zrobić 89 bajtów z PHP 5.5 (lub nowszym), ale to opóźnia wyzwanie o ponad 2 lata:

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

Uruchom jako potok z -nFlub wypróbuj je online .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.