Trouvez les facteurs premiers

23

Dans cette tâche, vous devez écrire un programme qui calcule les facteurs premiers d'un nombre. L'entrée est un nombre naturel 1 <n <2 ^ 32. La sortie est une liste des facteurs premiers du nombre dans le format suivant. Les exposants doivent être omis s'ils sont 1. Uniquement les nombres premiers en sortie. (En supposant que l'entrée est 131784):

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

Il n'est pas nécessaire d'utiliser la même quantité d'espace; un espace peut être inséré chaque fois que cela est approprié. Votre programme devrait se terminer en moins de 10 minutes pour toute entrée. Le programme avec le plus petit nombre de caractères gagne.

FUZxxl
la source
9
Points bonus si votre programme peut factoriser 685759991434940397765474496717275817990411426461294732612716997613329698095145054278980808884504301075550786464802304019795402754670660318614966266413770127 en moins de 73 jours!
Joey Adams
@Joey Adams: La factorisation commence avec 17 * 71 * 113 * 997 * 313597 ...
FUZxxl
3
@FUZxxl: Je pense que vous avez fait une erreur en copiant le numéro. C'est le produit de deux grands nombres premiers .
Joey Adams
@Joey Pouvons-nous utiliser l'algorithme de Shor?
Mateen Ulhaq
23
@Joey J'ai accidentellement renversé du café sur mon ordinateur quantique, et mon ami utilise le sien pour "pirater le gouvernement américain" ou quelque chose sans importance, alors, non. :(
Mateen Ulhaq

Réponses:

11

SageMath, 31 octets

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

Cas de test: 83891573479027823458394579234582347590825792034579235923475902312344444 Sorties:

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

12431234123412341234123
la source
Félicitations d'avoir remporté un défi avec votre tout premier message, beau travail! Et bienvenue sur le site!
DJMcMayhem
8

Ruby 1.9, 74 70 caractères

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

Modifications:

  • (74 -> 70) Utilisez simplement l'exposant comme longueur de tranche au lieu de vérifier explicitement exponent > 1
Ventero
la source
7

Perl 5.10, 73 88

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

Prend le numéro d'entrée de l'entrée standard. Calculera les facteurs pour plusieurs entrées si elles sont fournies.

Compté comme une différence pour perl -e. 5.10 est nécessaire pour le \Kmétacaractère regex.

JB
la source
+1 pour l'utilisation factor.
st0le
Ne devriez-vous pas compter l' poption?
Joey
@Joey en effet je devrais. Désolé pour ça. Fixation.
JB
Vous n'avez pas testé cela, mais au lieu de split/\D/,~factor $_~;$_="@_";pourriez-vous écrire $_=~factor $_~;s/\D/ /g;? (Bien sûr, remplacez ~par le backtick.)
Timwi
Tu veux dire $_=`factor $_`;s/\D/ /g;? Un double encastrement aide.
aaaaaaaaaaaa
5

OCaml, 201 caractères

Une traduction impérative directe du meilleur code 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

Par exemple,

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

(Notez que j'ai omis de produire la fin finale.) Juste pour le plaisir, à 213 caractères, une version purement fonctionnelle, complètement obscurcie par une utilisation libérale des opérateurs:

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
Matías Giovannini
la source
5

Python, 140 135 133 caractères

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:]
Keith Randall
la source
Je pense que la sortie nécessite quelques espaces supplémentaires, par exemple ' * %d'... Et deux autres choses 65536 == 4**8:; Ligne 7:if e:s+='*%d'%f+'^%d'%e*(e>1)
Oleh Prypin le
@BlaXpirit: "la même quantité d'espace n'est pas requise". Merci pour les deux autres, je vais les intégrer.
Keith Randall
5

J, 72

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

Typique J. Deux personnages pour faire la majeure partie du travail, soixante personnages pour le présenter.

Modifier: correction du nombre de caractères.

JB
la source
2
Cela ne ressemble pas à 62 caractères pour moi. Même en supposant que 161784c'est votre entrée, il reste 72 caractères.
Ventero
Ne serait-ce pas plus court avec |: __ q: y?
Eelvex
2
@Ventero: JB typique. Deux heures pour jouer au damné, quinze secondes pour gâcher le nombre de personnages.
JB
5

J, 53 52 characters

This solution takes the rplc trick from the solution of randomra but comes up with some original ideas, too.

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

In non-tacit notation, this function becomes

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

where g is defined as

g =: 3 : 0
": {. y) , '^' , (": # y) , '*'
)
  • q: yest le vecteur des facteurs premiers de y. Par exemple, les q: 60rendements 2 2 3 5.
  • x u/. ys'applique uà la y clé de x, c'est-à-dire, uest appliquée aux vecteurs d'éléments ydont les entrées dans xsont égales. C'est un peu complexe à expliquer, mais dans le cas particulier y u/. you u/.~ y, uest appliqué à chaque vecteur d'éléments distincts dans y, où chaque élément est répété aussi souvent qu'il y apparaît y. Par exemple, les </.~ 1 2 1 2 3 1 2 2 3rendements

    ┌─────┬───────┬───┐
    │1 1 1│2 2 2 2│3 3│
    └─────┴───────┴───┘
    
  • # yest le décompte de y, qui est, le nombre d'éléments y.

  • ": y formats y sous forme de chaîne.
  • x , y ajoute x et y.
  • {. yest la tête y , c'est-à-dire son premier élément.
  • Thus, (": {. y), '^' , (": # y) , '*' formats a vector of n repetitions of a number k into a string of the form k ^ n *. This phrase in tacit notation is :@{.,'^','*',~":@#, which we pass to the adverb /. described further above.
  • x rplc y is the library function replace characters. y has the form a ; b and every instance of string a in x is replaced by b. x is ravelled (that is, reshaped such that it has rank 1) before operation takes place, which is used here. This code replaces ^1* with * as to comply with the mandated output format.
  • }: y is the curtail of y, that is, all but its last item. This is used to remove the trailing *.
FUZxxl
la source
Couldn't you save a lot of work by using __ q:? Try it online!
Adám
@Adám Indeed, good idea!
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;}}
zzzzBov
la source
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:]
fR0DDY
la source
1
That's what I tried first, but it is too slow for big primes, like 4294967291.
Keith Randall
@Keith The question allows upto 10 minutes. Will this take more than 10 minutes for the worst case?
fR0DDY
2
It took 32 minutes on my machine for that number.
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))
Ry-
la source
3

Perl, 78

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

It uses the s///r feature of Perl 5.14 to elide the ^1s. 81 characters to run in a loop:

perl -Mntheory=:all -nE 'chomp;say join" * ",map{(join"^",@$_)=~s/\^1$//r}factor_exp($_);'
DanaJ
la source
You can leave out the spaces if you like. This would save two characters. Nice solution!
FUZxxl
2

PHP, 236 characters

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

Output for 131784: 2^3*3*17^2*19

Completes all numbers within a few seconds while testing.

4294967296=2^32
Time: 0.000168

Input was never specified, so I chose to call it using command line arguments.

php factorize.php 4294967296
Kevin Brown
la source
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("", "*", "")

ungolfed:

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 ("", "*", "")
user unknown
la source
2

J, 74 chars

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

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

64 chars with input in variable x:

   x=.131784

   (":x),'=',' '-.~('^1 ';'')rplc~}:,,&' *'"1(,'^'&,)&":/"{|:__ q:x
131784=2^3*3*17^2*19
randomra
la source
If you manage to turn this into a tacit definition, you can avoid escaping all the quotes. You could also use a 3 : 0 defintion.
FUZxxl
@FUZxxl I expected I can just put in the unescaped string in the 3 : 0 version but it didn't work somewhy. I might try tacit later though. This is the 3:0 I tried: pastebin.com/rmTVAk4j.
randomra
It should work. I don't see why. Did you name your argument y as you are supposed to?
FUZxxl
@FUZxxl This is the 3:0 I tried: pastebin.com/rmTVAk4j.
randomra
The 3:0 you tried doesn't exactly match the one-liner you provide. It uses '' instead of a: in one place. Maybe that's the difference?
FUZxxl
2

Java 10, 109 108 bytes (lambda function) (non-competing on request of 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;}

Try it online.

Java 6+, 181 bytes (full 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);}}

Try it online.

-1 byte thanks to @ceilingcat.

Explanation:

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
Kevin Cruijssen
la source
@ceilingcat Thanks!
Kevin Cruijssen
Disqualified as Java 10 was created after this task was published.
FUZxxl
@FUZxxl I've marked the Java 10 lambda as non-competing, and added a Java 6 program, which was released in December 2006.
Kevin Cruijssen
Okay, cool. That works for me!
FUZxxl
2

Japt, 28 27 26 bytes

-1 byte thanks to Shaggy

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

Try it

Oliver
la source
Disqualified as your language was created after this task was published.
FUZxxl
It was not allowed back when the challenge was posted. I consider it to be unfair to amend the rules of a challenge after the challenge has been posted, so languages published after this challenge remain illegal.
FUZxxl
1
@FUZxxl You don't have to accept my answer, but I am allowed to answer it regardless.
Oliver
1
24 bytes
Shaggy
1

Powershell, 113 97 bytes

Inspired by Joey's answer. It's a slow but short.

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

Explained test script:

$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

Output:

2
2*3^2*7
3*43
2^5*5*7^2*11
mazzy
la source
1

Jelly, 16 bytes (non-competing on request of OP)

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

One of my first Jelly answers, so can definitely be golfed (especially ³”=³)..

Try it online.

Explanation:

³                 # 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)
Kevin Cruijssen
la source
Disqualified as your language was created after this task was published.
FUZxxl
@FUZxxl Since mid-2017 non-competing isn't in the meta anymore, unless the challenge explicitly states that languages should be older than the time of posting. But if you as the one who posted the challenge chooses to not allow languages newer than your challenge post-date, I will edit my answers to add the explicit (non-competing). :)
Kevin Cruijssen
I believe the site consensus that was in place when this challenge was posted should define the rules for answers. Everything else (i.e. rules that change after the challenge was posted) would be unfair. Please mark your answers as non competing.
FUZxxl
@FUZxxl I've marked my answers as non-competing, as requested.
Kevin Cruijssen
Thank you for your help.
FUZxxl
1

05AB1E, 22 20 bytes (non-competing on request of OP)

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

-2 bytes thanks to @Emigna.

Try it online.

Explanation:

Ð                # 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)
Kevin Cruijssen
la source
1K should work instead of `≠iy in the loop.
Emigna
@Emigna Ah lol.. I actually do that in my Jelly answer I just posted. Not sure why I didn't think of it earlier here. :)
Kevin Cruijssen
Disqualified as your language was created after this task was published.
FUZxxl
1

APL(NARS), 66 chars, 132 bytes

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

test and comment:

  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

if someone has many time with these primitives, know them very well them, for me it is possible that the code is clearer of comments... so code more clear than comments, comments unuseful...

RosLuP
la source
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)
zzzzBov
la source
1
Has a trailing * in the output and prints the exponent even if it's 1.
Ventero
no need to downvote. There's nowhere that said that it couldn't print the exponent if it's 1. Also, the trailing * assumes multiplying by 1. If it's that big an issue, I'll fix it.
zzzzBov
1
»in the following format« in the task description pretty much implies that an exponent of 1 should not be printed. And no, a trailing * is also against that. If one could choose the output format that freely, then shelling out to factor(1) would be the easiest one. Answers can only reasonably compared if they all solve the same problem.
Joey
3
As the creator of this task, I say, that the exponents have to be omitted if 1 and only prime-numbers can be factors.
FUZxxl
0

PHP, 112 bytes

<?=$a=$argn,"=";for($i=2;1<$a;)$a%$i?$i++:$a/=$i+!++$r[$i];foreach($r as$k=>$v)echo$t?"*":!++$t,$v<2?$k:"$k^$v";

Try it online!

Jörg Hülsermann
la source
0

PHP, 93 bytes

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

I could do 89 bytes with PHP 5.5 (or later), but that postdates the challenge by more than 2 years:

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

Run as pipe with -nF or try them online.

Titus
la source