Stampa la scomposizione in fattori primi del massimo comun divisore di due numeri


17

Il titolo dice tutto. Due numeri interi positivi a 32 bit di input m, n >= 2, output gcd(m,n)in forma di fattorizzazione primaria.

Ingresso

Argom della riga di comando o 1 riga di stdin va bene, qualunque cosa sia meglio per il golf.

Produzione

Spazio singolo delimitato da esponenti (senza spazi aggiuntivi). Non produce nulla se gli ingressi sono relativamente primi.

Esempi:

$ ./factorize 96 162
2^1 3^1

$ ./factorize 14 15


$ ./factorize 196 294
2^1 7^2

Regole

  • Non è possibile utilizzare risorse esterne, librerie matematiche o funzioni integrate per la fattorizzazione o GCD. Esempi: Java, n java.lang.Math. rubino, no prime_division, perl, no factor, ecc.

1
Quale output stai cercando se gcd(n,m) == 1?
undergroundmonorail,

Va bene se esco con un'eccezione? Mi farebbe risparmiare qualche byte.
undergroundmonorail,

In realtà, ho cambiato il mio approccio e non ho bisogno di uscire con un'eccezione. Altri potrebbero voler sapere, però.
undergroundmonorail,

Non uscire con un'eccezione. Non viene prodotto nulla :)
durron597,

Tecnicamente, q:a+.bo __ q:a+.bin J non usa external resources or math libraries, ma non lo pubblicherò, poiché è troppo lontano dallo spirito della domanda. Ho solo pensato di condividerlo qui.
ɐɔıʇǝɥʇuʎs,

Risposte:


10

Python 3, 255 250 237 226 188 180 150 142 137 136 caratteri

a,b=map(int,input().split())
t,g='',1
while g<a:
 g,p=g+1,0
 if a%g+b%g<1:
  while a%g+b%g<1:a/=g;b/=g;p+=1
  t+='%d^%d '%(g,p)
print(t)

È incredibile quanto potrei accorciarlo semplicemente saltando cose (come, sai, trovando il gcd)! Inoltre potrei ridurre altri 10 caratteri rendendo questa una funzione che prevede 2 in, come alcune altre risposte, invece di leggere dallo stdin.


Questo è intenso! Sto imparando molto guardando le tue modifiche e cercando di batterti lol. Penso che potresti averne uno però (dalle risposte di Python)
Rainbolt

1
Puoi salvare 1 personaggio cambiando while g<a and g<b:inwhile(g<a)*(g<b):
Rainbolt

@Rusher Grazie amico! La tua risposta è quella che mi ha motivato a lavorare di più su questo :) Anche il trucco che mi ha raccomandato ispirato a capire il a%g+b%gbit
Tal

Non penso che la clausola else sia necessaria. else:g+=1potrebbe essere g+=1, a meno che non mi manchi qualcosa.
isaacg,

@isaacg Sembra che tu abbia ragione, grazie!
Tal

8

Rubino - 168 117 114 101 100 97

Modifica: dopo averci pensato, mi sono reso conto che non avevo bisogno del setaccio poiché la primalità del fattore è curata nel ciclo di fattorizzazione. Inoltre, come informato dalle risposte di altri ( quelli di Laindir e Tal sono quelli in cui l'avevo visto, anche se sembra che anche altri lo abbiano fatto), rimosso il calcolo separato del gcd, poiché ciò si verifica anche nella fattorizzazione.
Modifica 2: non è necessario do.
Modifica 3: comprimendolo di più.
Modifica 4: estratto uno spazio in più.
Modifica 5: uptoanziché each; ?^ == "^"!

a,b=ARGV.map{|i|i.to_i}
2.upto(a){|d|c=0
[c+=1,a/=d,b/=d]while a%d+b%d<1
print d,?^,c," "if c>0}

Output (lo stesso dopo la modifica):

$ ruby factorize.rb 96 162
2^1 3^1 
$ ruby factorize.rb 14 15

$ ruby factorize.rb 196 294
2^1 7^2 

Certamente potrebbe essere migliorato, ma non male per il mio primo.


È possibile rimuovere 4 byte cambiando map{|i|i.to_i}in map &:to_i. È possibile rimuovere un quinto byte non contando la nuova riga alla fine del file; Ruby lavora senza di essa.
kernigh,

Inoltre, puoi usare $*invece di ARGV.
daniero,

6

Python 2 - 254 252 196 185 156 151 134 126 121

i=1
a,b=map(int,raw_input().split())
while b:a,b=b,a%b
while~-a:
 i+=1;j=0
 while a%i<1:j+=1;a/=i
 if j:print`i`+'^'+`j`,

Interprete

repl.it

Esempio di input - stdin

100 50

Esempio di output - stdout

2 ^ 1 5 ^ 2


1
Che dire …`a`+'^'+`f.count(a)`…?
Ry,

Abbastanza pulito, mi piace
qwr

@qwr Grazie. Spero di poter capire le altre risposte di Python sulla formattazione delle stringhe e radere alcuni caratteri.
Rainbolt

Scambia f.append(i)per f+=[i]salvare 5 caratteri.
Nolen Royalty

1
E ora non è necessario usare f affatto: p (perché è f=''ancora lì?)
Nolen Royalty

4

Java - 184 175

Questo si ispira alla risposta di @Geobits (e un po 'della risposta di @ Tal), ma abbastanza è diverso che ho deciso di creare la mia risposta.

class G{public static void main(String[]a){for(Integer i=1,q,n=i.valueOf(a[0]),m=i.valueOf(a[1]);m>=++i;System.out.print(q>0?i+"^"+q+" ":""))for(q=0;n%i+m%i<1;n/=i,m/=i)q++;}}

Imbracatura non rigata (sorta di) con (verifica umana):

class G {
    public static void mainMethod(String[] a) {
        for (Integer i = 1, q, n = i.valueOf(a[0]), m = i.valueOf(a[1]); m >= ++i;
                 System.out.print(q > 0 ? i + "^" + q + " " : ""))
            for (q = 0; n % i + m % i < 1; n /= i, m /= i)
                q++;
    }

    public static void main(String[] a) {
        m(3, 3);
        m(196, 294);
        m(294, 196);
        m(14, 15);
        m(15, 14);
        m(96, 162);
        m(162, 96);
        m(300, 400);
        m(400, 300);
        m(100, 100);
        m(7, 7);
        m(4, 8);
    }

    public static void m(int one, int two) {
        mainMethod(new String[] { String.valueOf(one), String.valueOf(two) });
        System.out.println();
    }
}

4

dc, 96 byte

?sbsa2sf[q]sk[lalf~lblf~szrlz+0<ksbsale1+selsx]ss[lfn[^]Plen[ ]P]sp[0selsxle0<plf1+dsflb!<w]dswx

Legge una riga di input standard. Il suo output non termina con una nuova riga. (EDIT: genera anche uno spazio extra dopo ogni fattorizzazione. Alcune delle altre risposte tagliano lo spazio, ma questa no.)

Esempio:

$ echo 301343045 421880263 | dc factorize.dc
1021^1 59029^1 $ 

Codice con commenti:

# dc(1) is a stack language, like Forth. Programs push values on the
# stack, then operate on them. For example, to calculate
#  (2 + 3) * (9 - 4)
# the dc code is
#  [2 3 + 9 4 - *]

# [?] reads a line of input.  We expect two integers >= 2.
# [sb sa] stores the integers in variables.
? sb sa     # a, b = two integers from input

# This program sucks common factors from a and b, looping for
# f = 2, 3, 4, 5, and so on.  This method only sucks prime factors,
# but wastes time when f is not prime.
2 sf        # f = 2

# Code in [...] does not run until the program calls it.

# k = code to break a loop
[
 q           # [q] breaks two levels of [...]
] sk        # k = break

# s = loop to suck factor f from a and b
#  This loop increments e, the exponent for factor f.
#  Please set e = 0 before entering this loop.
[
 # [la lf] puts ( a f ) on the stack.
 # [~] does division and remainder.
             # STACK:
 la lf ~     # ( a/f a%f )
 lb lf ~     # ( a/f a%f b/f b%f )

 # [r] swaps the top two stack values.
 # Hold z = b%f and swap a%f with b/f.
             # STACK:
 sz r lz     # ( a/f b/f a%f b%f )

 # f is a common factor if a%f and b%f are zero.  Because a and b are
 # non-negative, a%f and b%f are zero only if a%f+b%f is zero.
             # STACK:
 +           # ( a/f b/f a%f+b%f )

 # Call k to break loop unless a%f+b%f is zero.  [<k] conditionally
 # calls k if the comparison is true.  Comparisons in dc are
 # backwards, so [3 0 <k] would check 0 < 3.  Because a%f+b%f is never
 # negative, [0 <k] is golf for [0 !=k].
             # STACK:
 0 <k        # ( a/f b/f )

 # f is a common factor, so suck it!
 sb sa       # a = a/f, b = b/f, STACK: ( )
 le 1 + se   # increment e, the exponent for this factor
 ls x        # continue loop, [x] executes s
] ss        # s = loop

# p = code to print "f^e "
[
 # [n] prints a number without a newline.
 # [P] prints a string.
 lf n [^]P
 le n [ ]P

 # DEBUG: Uncomment to print a and b.
 #[(a = ]P la n [, b = ]P lb n [)]P 10P
] sp        # p = print

# w = loop to iterate factors
[
 # Call s loop to suck factor f from a and b, and set exponent e.
 0 se        # e = 0
 ls x        # call s loop

 # DEBUG: Uncomment [c] to clear the stack.  Loop s leaves two junk
 # values ( a/f b/f ) on the stack.  Deleting [c] for code golf saves
 # 1 byte but leaks junk on the stack.
 #c

 # Print "f^e " if 0 < e.  Comparisons in dc are backwards, so
 # [0 le <p] would check e < 0, [le 0 <p] checks 0 < e.
 le 0 <p

 # Increment f.  [d] duplicates top value on stack.
             # STACK:
 lf 1 +      # ( f+1 )
 d           # ( f+1 f+1 )
 sf          # ( f ) as f+1 becomes f

 # Continue loop if b >= f.  This is golf for f <= a and f <= b, as
 # extra iterations of the loop cause no harm.
             # STACK:
 lb          # ( f b )
 !<w         # ( ), continue loop if not b < f
] d sw      # w = loop; STACK: ( w )
x           # enter loop unconditionally; STACK: ( ) at entrance

3

PowerShell - 82

$a,$b=$args
2..$a|%{$p=0;while(!($a%$_+$b%$_)){$a/=$_;$b/=$_;$p++}if($p){"$_^$p"}}

Questo è breve e facile da leggere. Inoltra l'intervallo 2..$ain un ciclo Foreach-Object %{...}. Il loop raccoglie i valori di if($p){"$_^$p"}.
kernigh,

3

JavaScript (bozza ECMAScript 6) - 89 caratteri

f=(m,n,i=2,k=0)=>(m%i|n%i?(k?i+'^'+k+' ':'')+(i>m?'':f(m,n,i+1)):f(m/i,n/i,i,k+1)).trim()

Converte la risposta originale (iterativa), di seguito, in una ricorsiva.

Spiegazione

f=(m,n,i=2,k=0)=>           // A function with arguments m and n and optional arguments
                            // i (defaults to 2) and k (defaults to 0)
  (
    m%i|n%i                 // if i is not a divisor of m or n then:
      ?(k?i+'^'+k+' '       //   if k is non-zero append  "i^k " to the output
         :'')               //   else append nothing
        +(i>m?''            //   if i>m then terminate
             :f(m,n,i+1))   //   else increment i and reset k to 0
      :f(m/i,n/i,i,k+1)     // else divide m and n by i and increment k
  ).trim()                  // finally strip any extra spaces from the output.

Risposta iterativa: JavaScript (ECMASCript 6) - 108 (o 121) 98 caratteri

Versione 2:

f=(m,n)=>{for(s='',i=1;++i<=m;s+=k?' '+i+'^'+k:'')for(k=0;m%i+n%i<1;k++)m/=i,n/=i;return s.trim()}

Versione 1:

Rispondere alla domanda come inizialmente chiesto:

f=(m,n)=>{for(o=[],i=2;i<=m;)m%i|n%i?i++:(m/=i,n/=i,o[i]=(o[i]|0)+1);return o.map((x,i)=>i+"^"+x).join(' ')}

O per rispettare le modifiche alla regola dopo il fatto:

f=(m,n)=>{for(o=[],i=2;i<=m;)m%i|n%i?i++:(m/=i,n/=i,o[i]=(o[i]|0)+1);return o.map((x,i)=>i+"^"+x).filter(x=>x).join(' ')}

Spiegazione

f=(m,n)=>                        // Create a function f with arguments m and n
{
  o=[]                           // Initialise an empty array for the output
  i=2                            // Start with a divisor of 2
  for(;i<=m;)                    // Loop while the divisor is not greater than m
    m%i|n%i                      // Test the bitwise OR of m%i and n%1 (i.e. whether
                                 // at least one is non-zero)
      ?i++                       // If m%i>0 or n%i>0 then increment i
      :(m/=i,                    // Otherwise: divide m by i;
        n/=i,                    //                   n by i;
        o[i]=(o[i]|0)+1);        // and add 1 to the i-th element of o
  return o.map((x,i)=>i+"^"+x)   // finally map the sparse array o to a sparse array
                                 // of the strings (index+"^"+value)
          .filter(x=>x)          // turn sparse array into non-sparse array
          .join(' ')             // then concatenate and return.
}

Produzione

f(96,162)
"2^1 3^1"

f(14,15)
""

f(80, 80)
"2^4 5^1"

f(196,294)
"2^1 7^2"

Ehi, puoi provare per f(158,237)favore
Durron597,

È spazio delimitato da esponenti (capita che abbia molto spazio)" 79^1"
MT0

Bene, le altre soluzioni non hanno questo e nemmeno l'esempio. Si prega di risolvere :)
durron597

Nulla nella domanda, come inizialmente chiesto, definisce quanto spazio bianco è o non è permesso - a mio avviso, questo soddisfa i requisiti in quanto spazio bianco delimitato da esponenti. Tuttavia, hai intenzione di andare e cambiare le regole ora non è vero?
MT0,

2
Secondo le regole preesistenti, si potrebbe dire che questa implementazione omette il requisito "Non produrre nulla se gli input sono relativamente primi". Sembra ancora sbagliato sfigurare il codice di golf che è uscito così carino. Quanto breve è possibile effettuare una filter()chiamata?
Appassionato del

3

Perl 6: 90 caratteri, 94 byte

sub MAIN(*@n){@n.any%$_||(my$p=$p⊎$_;@n»/=»$_;redo)for
2..@n[0];$p.pairs.fmt("%d^%d").say}

Un po 'decodificato e commentato:

sub MAIN (*@n) { # accept any number of input numbers as @n
    (
        # $p is a Bag, e.g., it holds the primes and the number of times each was added
        my $p = $p ⊎ $_; # Add the prime to the bag
        @n »/=» $_; # Divide all the input numbers by the prime

        redo # Redo the loop iteration with the same prime, in case
             # the numbers can be divided by it multiple times
    )
    if @n.all %% $_ # Do the above only if all of @n are divisible by $_
    for 2..@n[0];   # Do the above for all numbers from 2 .. @n[0]

    $p.pairs.fmt("%d^%d").say # Print join " ", "$prime^$count"
}

L'uso è come:

$ perl6 -e'sub MAIN(*@n){@n.any%$_||(my$p=$p⊎$_;@n»/=»$_;redo)for
2..@n[0];$p.pairs.fmt("%d^%d").say}' 51 153
3^1 17^1

⊎ è un simbolo in perl? Non lo sapevo.
durron597,

@ durron597 Solo Perl 6 :)
Mouq,

3

Perl, 144 133 118 114 97 93

($a,$b)=<>=~/\d+/g;for(2..$a){for($n=0;$a%$_+$b%$_<1;$n++,$a/=$_,$b/=$_){}$n&&print"$_^$n ";}

Versione non golfata:

($a,$b)=<>=~/\d+/g;
for(2..$a){
    for($n=0 ; $a%$_+$b%$_<1 ; $n++,$a/=$_,$b/=$_) {}
    $n&&print"$_^$n ";
}

Ho appena iniziato a imparare il Perl solo per rispondere a questa domanda (questo è il mio primo codice Perl in assoluto), quindi sospetto che questo possa essere ulteriormente approfondito.


Sì, non ho esaminato attentamente il tuo codice, ma foreachè sempre sinonimo di forin Perl 5, quindi dovrebbe tagliare 4 caratteri :)
Mouq,

@Mouq Non ho mai visto una lingua con così tanta ridondanza ... grazie :)
Tal

2

Java: 247 241

Tiene traccia dei fattori in un array e li stampa semplicemente in un ciclo.

Dimensioni decenti per Java, a quanto pare.

class G{public static void main(String[]a){Integer i=1;int n=i.valueOf(a[0]),m=i.valueOf(a[1]),f[]=new int[n>m?n:m+1];for(;m>=++i||n>i;){if(n%i+m%i<1){f[i]++;n/=i;m/=i--;}}for(i=2;i<f.length;System.out.print(f[i]>0?i+"^"+f[i]+" ":""),i++);}}

// line breaks below

class G{
    public static void main(String[]a){
        Integer i=1;int n=i.valueOf(a[0]),m=i.valueOf(a[1]),f[]=new int[n>m?n:m+1];
        for(;m>=++i||n>i;){
            if(n%i+m%i<1){
                f[i]++;n/=i;m/=i--;
            }
        }
        for(i=1;i<f.length;System.out.print(f[i]>0?i+"^"+f[i]+" ":""),i++);
    }
}

In realtà puoi lasciare le altre variabili come int, perdi 4 a int ma le riacquisti con new int[-> new Integer[quindi è un lavaggio.
durron597,

Sì, e ne ho altri tre passando n%i<1&&m%i<1a n%i+m%i<1.
Geobits

Non hai bisogno del (). In caso n==mcontrario, per impostazione predefinita m+1.
Geobits

2
Puoi sostituirlo m/=i;i=1;con m/=i--;
Funzionerà

1
Sono necessarie le parentesi graffe dopo il primo forciclo?
Ypnypn,

2

JavaScript (ECMAScript 5) 170 164 163 113

Praticamente non ho potuto resistere seguendo l'esempio di MT0. Prima avevo considerato la ricorsione, ma mi era sembrato troppo facile sbagliare. E lo è davvero. La minima variazione rovina tutto.

C'è un violino per chi ama i violini.

function f(a,b,i,e){return i?a%i|b%i?(e?i+'^'+e+' ':'')+(i>a?'':f(a,b,i+1,0)):f(a/i,b/i,i,e+1):f(a,b,2,0).trim()}

Ungolfed:

function f(a,b,i,e){
    return i // Check for factor.
        ?a%i|b%i // Check for indivisibility.
            ?(
                e // Check for exponent.
                    ?i+'^'+e+' ' // Add the current factor to result string.
                    :'' // Omit the current non-factor.
             )+(
                i>a // Check for termination state.
                    ?'' // Stop recursion.
                    :f(a,b,i+1,0) // Go to the next factor.
            )
            :f(a/i,b/i,i,e+1) // Failed indivisibility check. Increment exponent and divide subject values.
        :f(a,b,2,0) // Add default factor and exponent.
        .trim() // Get rid of one extra space that's usually on the end.
}

Vecchia versione

function f(a,b){for(var r=[],j=-1,i=2;i<=a;)a%i|b%i?++i:(r[j]&&r[j][0]==i?r[j][1]++:r[++j]=[i,1],a/=i,b/=i);for(j=0;i=r[j];++j)r[j]=i.join('^');return r.join(' ')}

Ungolfed:

function f(a,b){
    for(var r=[],j=-1,i=2;i<=a;)
        // We (mis)use conditional expression `?:` instead of `if(){}else{}`.
        a%i|b%i ? // Bitwise OR saves one character over logical OR, where applicable.
             // In the truth case, `i` has become uninteresting. Just move on.
            ++i : // We don't mind hitting composites because their prime factors have already been drained from `a` and `b`.
            (
                r[j]&&r[j][0]==i ? // Check if `i` is already a listed factor.
                    r[j][1]++ : // Increment the exponent count.
                    r[++j]=[i,1], // Otherwise, add a new factor with exponent 1.

                a/=i,b/=i // Drain a used-up factor from `a` and `b`.
            );

    // The real work's done. Now we just format.
    for(j=0; i=r[j]; ++j)
        r[j]=i.join('^'); // Join each factor to its exponent.

    return r.join(' ') // Join all factors into result string.
}

Ecco alcuni test:

[
    f(4, 12),
    f(80, 80),
    f(96,162),
    f(196,294)
];

Questa funzione ricorsiva non è riuscita f(301343045, 421880263);probabilmente perché il mio browser non mi consente di ricorrere in profondità. Firefox stupido rotto!
kernigh,

Certamente. In pratica, utilizzerei una funzione ricorsiva solo se avessi davvero bisogno di un qualche tipo di stack, come per la navigazione ad albero o altre strutture di dati intrinsecamente ricorsive. (Certo, i numeri possono essere trattati come strutture di dati ricorsive, ma abbiamo tutti i tipi di belle astrazioni per aiutarci a ignorare questo fatto.)
Appassionato del

2

GolfScript, 68 byte

~..),2>*${1$1$%3$2$%+!{.@@/@2$/.}*;}/;;]:D.&{`.[~]D\/,(`"^"\++}%" "*

Si noti che questo approccio richiede O (b 2 ) tempo e spazio per numeri interi "a" e "b".

Al costo di un byte extra, sono necessari "solo" O (b) tempo e spazio:

~.),2>31*${1$1$%3$2$%+!{.@@/@2$/.}*;}/;;]:D.&{`.[~]D\/,(`"^"\++}%" "*

Come funziona

~.        # Interpret the input string (“a” and “b”) and duplicate “b”.
.),2>     # Push the array [ 2 3 4 ... b ].
*$        # Repeat each element b times and sort: [ 2 ... 2 3 ... 3 ... b ... b ]
{         # For each element “d” of the array:
  1$1$%   # Calculate a % d.
  3$2$%   # Calculate b % d.
  +!      # Add and negate.
  {       # If both “a” and “b” are divisible by “d”:
    .@@/  # Calculate a / d.
    @2$/  # Calculate b / d.
    .     # Create a dummy value.
  }*      #
  ;       # Pop the topmost stack element (non-divisor “d” or dummy value).
}/        #
;;]       # Pop “a” and “b” and collect the remaining stack elements in an array.
:|.&      # Save that array in “D” and intersect it with itself to deduplicate it.
{         # For each element “d” of “D”:
  `.[~]   # Push string "d" and array [d].
  D\/,(`  # Split “D” around [d] and take the length minus 1. This count the occurrences.
  "^"\    # Push the string "^" and swap it between "d" and it's number of occurrences.
  ++      # Concatenate the three strings.
}%        # Collect all strings into an array.
]" "*     # Join by spaces.

1

Python 3 (123)

Questo utilizza sostanzialmente la stessa struttura della risposta di Tal .

a,b=map(int,input().split())
s='';p=1
while p<a:
 c=0;p+=1
 while a%p+b%p<1:a/=p;b/=p;c+=1
 if c:s+='%d^%d '%(p,c)
print(s)

È sufficiente eseguire il ciclo fino a p = a-1, poiché incrementiamo immediatamente per ottenere p = ae a> = min (a, b). Se b> a, non c'è nulla di male nel provare valori inutili di p sopra a.

In 2.X, penso che potremmo risparmiare caratteri stampando ogni pezzo come abbiamo più, piuttosto che accumulare una stringa: if c:print'%d^%d'%(p,c),. Python 3, sfortunatamente, non sembra avere un modo compatto per stampare senza una nuova riga finale.


1

PHP, 96

<?php
list(,$a,$b)=$argv;for($s=1;$s++<$a;$c&&print"$s^$c ")for($c=0;1>$a%$s+$b%$s;$a/=$s,$b/=$s)$c++;

Abbiamo quasi esattamente lo stesso codice! Il mio unico miglioramento è quello di combinare p=0;g+=1in una riga iniziando ginvece da 1, il che ti consente quindi di fare g<apiuttosto che g<=a. Spero che ti piaccia il pitone.
xnor

@xnor Ho perso il tuo codice. In effetti è quasi lo stesso. Ho rimosso il mio script Python. Spero che non mi piacerà il pitone, HO BISOGNO delle parentesi graffe
mleko

Non è necessario rimuovere il codice, te lo sei inventato da solo. Ho anche inventato la cosa del gioco come Tal, quindi sembra proprio questo a cui converge il golf Python.
xnor

1

awk - 115 111 96 85

La nuova versione può gestire solo una riga di input. Grazie a durron597 per aver sottolineato che ho solo bisogno di essere sicuro i <= $1.

{for(i=1;++i<=$1;)for(;$1%i+$2%i==0;f[i]++){$1/=i;$2/=i}$0=z;for(i in f)$i=i"^"f[i]}1

Ungolfed:

{
    #skip finding gcd as a separate step, get it from the factors
    for(i = 1; ++i <= $1;) {
        for(;$1 % i == 0 && $2 % i == 0; f[i]++) {
            $1 /= i;
            $2 /= i;
        }
    }
    $0 = "";
    for(i in f) {
        $i = i "^" f[i];
    }
    print;
}

In precedenza poteva prendere più volte coppie di numeri

{a=$1;b=$2;for($0=c;a-b;)if(a>b)a-=b;else b-=a;for(i=2;i<=a;i++){for(j=0;a%i==0;j++)a/=i;$0=$0(j?i"^"j" ":c)}}1

Ungolfed:

{
    a = $1;
    b = $2;
    $0 = "";
    #rip off Euclid
    for(; a != b;) {
        if(a > b) {
            a = a - b;
        } else {
            b = b - a;
        }
    }
    #but not Eratosthenes
    for(i = 2; i <= a; i++) {
        for(j = 0; a % i == 0; j++) {
            a /= i;
        }
        $0 = $0 (j ? i "^" j " " : "");
    }
    print;
}

Ti serve &&i<=b?
durron597,

Bene, avrò ... hai ragione, no: se i > b, allora b % i != 0... grazie :)
Laindir,

Questo programma non funziona con awk in OpenBSD 5.5, perché NF=0;non riesce a eliminare $ 1 e $ 2. L'output da echo 301343045 421880263 | awk -f factorize.awk | sed 's/ */ /g'è 5 7 1021^1 59029^1perché $ 1 è 5 e $ 2 è 7. La sed comprime gli spazi extra che provengono dalla stampa di $ 1022, $ 1023, $ 1024, ..., $ 59028 come stringhe vuote unite da spazi.
kernigh,

Grazie @kernigh, funziona in nawk, mawk e gawk. Ricontrollato che posix non dice nulla sull'assegnazione a NF, e sostituito con$0=z;
laindir,

@laindir Quella modifica risolve il programma per me. Code golf non richiede che i programmi siano portatili. Fortunatamente $0=z;è lo stesso numero di personaggi diNF=0; . Se $0=z;fosse più lungo, ti direi di continuare NF=0;.
kernigh,

1

Pip , 41 byte

Non è una risposta concorrenziale, poiché la lingua è più recente della domanda. Ma quel marchio GolfScript del 68 doveva scendere.

Fi2,++a{p:0T$|g%i{++pg/:i}Ipx.:i.'^.p.s}x

L'output termina in uno spazio; se questo è un problema, anche la seguente versione è di 41 byte (incluso il -sflag):

Fi2,++a{p:0T$|g%i{++pg/:i}IplAE:i.'^.p}l

Formattato, con spiegazioni:

F i 2,++a {      For i in range(2,a+1); note ++ used to avoid parentheses in 2,(a+1)
  p:0            p will store the greatest power of i that divides both numbers
  T $+(g%i) {    Loop till the sum of g%i is nonzero, where g is a list initialized
                  from cmdline args
    ++p          As long as g%i is [0 0], increment p...
    g/:i         ...and divide both numbers in g by i
  }
  I p            If p is nonzero, i went into both numbers at least once
    x.:i.'^.p.s  Append i^p and a space to the result
}
x                Print the result

Pip, a differenza di GolfScript, CJam, et al. è un linguaggio imperativo con operatori infix; prende anche ispirazione dai linguaggi di programmazione di array. Questa attività mostra bene entrambi i paradigmi al lavoro.

(Nota che per eseguire questo è necessario il commit 2015-4-20, poiché ho appena corretto un paio di bug.)


0

Python 2 - 262 byte

n,m=input(),input()
f=lambda i:set(filter(lambda x:i%x<1,range(1,i+1)))
g=max(f(n)&f(m))
p=[]
while g-1:
 p+=[min(filter(lambda x:x>1 and x%2!=(x==2)and not any(map(lambda y:x%y<1,range(2,x))),f(g)))]
 g/=p[-1]
print ' '.join(`a`+^+`p.count(a)`for a in set(p))

La linea 6 ha bisogno di lavoro.


1
Che dire …`a`+'^'+`f.count(a)`…?
Ry,

Non ho idea di come mi sia perso. Jeez. Grazie.
undergroundmonorail,

0

Groovy: 174 caratteri

Questa è una porta della soluzione di Geobits a Groovy 2.2.1:

int i=1, n=args[0]as int, m=args[1]as int;s=n>m?n:m+1;f=new int[s];while(m>=++i||n>i){if(n%i+m%i<1){f[i]++;n/=i;m/=i--;}};(s-1).times{y=it+1;x=f[y];print"${x>0?"$y^$x ":""}"}

Ecco la versione ungolfed:

int i = 1, n = args[0] as int, m = args[1] as int

s = n>m?n:m+1
f = new int[s]

while (m>=++i||n>i) {
    if (n%i+m%i<1) {
        f[i]++;n/=i;m/=i--;
    }
}
(s-1).times {
    y=it+1
    x=f[y]
    print"${x>0?"$y^$x ":""}"
}

Sorpreso, hai scelto di trasferire la soluzione di Geobits al posto della mia, poiché la mia è più corta di 56 caratteri
durron597,

0

R: 139

a=scan();q=1:a[1];n=max(q[!a[1]%%q&!a[2]%%q]);m=rep(0,n);for(i in 2:n){while(!n%%i){m[i]=m[i]+1;n=n/i};if(m[i])cat(paste0(i,"^",m[i])," ")}

Con rientri:

a=scan() #Take space-separated numeric input from stdin
q=1:a[1]
n=max(q[!a[1]%%q&!a[2]%%q]) #gcd
m=rep(0,n)
for(i in 2:n){
    while(!n%%i){ #prime factorization
        m[i]=m[i]+1
        n=n/i
        }
    if(m[i])cat(paste0(i,"^",m[i])," ")
    }

Uso:

> a=scan();q=1:a[1];n=max(q[!a[1]%%q&!a[2]%%q]);m=rep(0,n);for(i in 2:n){while(!n%%i){m[i]=m[i]+1;n=n/i};if(m[i])cat(paste0(i,"^",m[i])," ")}
1: 196 294
3: 
Read 2 items
2^1  7^2  
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.