Radici fattoriali Prime


14

Ispirato alle radici digitali, la radice fattoriale primaria di un numero è il numero che emerge quando si prendono i fattori primi di un numero, li si sommano e si ripete il processo sul numero risultante, continuando fino a quando non si ottiene un numero primo ( che ha se stesso come unico fattore primo ed è quindi la sua radice fattoriale principale). La radice del fattore primo primario di 4 è 4, come 2 * 2 = 2 + 2, e questa è l'unica radice del fattore primo non-primo di un numero intero maggiore di 1 (che è un altro caso speciale, in quanto non ha fattori primi). La sequenza OEIS formata da radici fattoriali prime è A029908 .

Ad esempio, la radice fattoriale primaria di 24 è:

24=2*2*2*3

2+2+2+3=9=3*3

3+3=6=2*3

2+3=5, and the only prime factor of 5 is 5.  Therefore, the prime factoral root of 24 is 5.  

Il tuo compito:

Scrivi un programma o una funzione che trova la radice fattoriale primaria di un intero di input.

Ingresso:

Un numero intero, immesso tramite qualsiasi metodo ragionevole, compreso tra 2 e il numero intero più grande supportato dalla tua lingua (incluso). In particolare, non è consentito scegliere una lingua che abbia una dimensione intera massima irragionevolmente bassa (e viola anche questa scappatoia standard )

Produzione:

Un numero intero, la radice fattoriale primaria dell'input.

Casi test:

4   -> 4
24  -> 5
11  -> 11
250 -> 17

punteggio:

Questo è , il punteggio più basso in byte vince!


3
Puoi aggiungere 4casi di test, dal momento che è un'eccezione ed è facile dimenticarsene durante il test di una risposta?
scottinet,

Dobbiamo produrre 1 per 1?
mio pronome è monicareinstate il

@someone secondo la sequenza OEIS collegata, dovrebbe produrre 0 per 1
scottinet

2
@someone La sfida afferma che l'input sarà almeno 2.
Martin Ender il

@someone Ci scusiamo per un po 'di tempo. Come ha detto Martin, la sfida afferma specificamente che l'input sarà maggiore di uno e quindi il comportamento quando l'ingresso è 1 non è definito.
Gryphon,

Risposte:



14

Haskell , 61 byte

import Data.Numbers.Primes
until=<<((==)=<<)$sum.primeFactors

Provalo online!

Spiegazione

until=<<((==)=<<)accetta una funzione fe la applica all'input xfino al raggiungimento di un punto fisso, ovvero f xuguale x. primeFactorsrestituisce l'elenco dei fattori primi di un numero, sumrestituisce la somma di un elenco di numeri.

Ma aspetta, perché until=<<((==)=<<) il lavoro e sembra così strano?

Se assumiamo f=sum.primeFactors, una definizione più naturale sarebbe until(\x->f x==x)f, poiché untilprende un predicato (una funzione che restituisce un valore booleano), una funzione che ha lo stesso tipo di input e return (ad esempio Int -> Int) e valore di questo tipo, e quindi applica la funzione al valore fino al completamento del predicato.

until(\x->f x==x)fè lo stesso until(\x->(==)(f x)x)f, e come sostiene che g (h x) xè lo stesso di (g=<<h)x, otteniamo until(\x->((==)=<<f)x)f. Dopo la conversione Eta , questo diventa until((==)=<<f)f. Ma se ora trattiamo (==)=<<come una funzione che viene applicata f, possiamo vedere che until(((==)=<<)f)fè ancora della forma g (h x) x, con g=until, h=((==)=<<)e x=f, quindi può essere riscritto per (until=<<((==)=<<))f. L'uso $dell'operatore per sbarazzarsi delle parentesi esterne e la sostituzione fcon sum.primeFactorsproduce la soluzione dall'alto.


4
=<<((==)=<<)$Whaaaaaat.
totalmente umano il

2
@icrieverytim Ho aggiunto una spiegazione. Sentiti libero di chiedere nella chat room di Haskell se hai ulteriori domande su come funziona questa stregoneria.
Laikoni,

5

Buccia , 4 byte

ω(Σp

Provalo online!

Spiegazione:

ω(   -- apply the following function until the result no longer changes (fixpoint)
  Σ  -- sum
   p -- the list of primefactors


4

Python 2 , 84 byte

f=lambda n,d=2:n>1and(n%d and f(n,d+1)or d+f(n/d))
i=input()
exec'i=f(i);'*i
print i

Provalo online!


Questa potrebbe essere una domanda piuttosto stupida, ma come f=lambda n,d=2:n>1and(n%d and f(n,d+1)or d+f(n/d))funziona? Non ho mai programmato in Python (principalmente Java e C #), quindi non sono sicuro di quale sia il risultato di questa funzione. Questa funzione modifica l'input ne lo restituisce in seguito, oppure è simile a un valore booleano dove n>1and(n%d and f(n,d+1)or d+f(n/d))è 0 o 1, oppure 0 o n, o qualcos'altro? Sto cercando di visualizzare come apparirebbe una porta di questo in Java / C #, ma non ci riesco perché non capisco davvero le lambda di Python come questa in generale.
Kevin Cruijssen,

1
@KevinCruijssen questo equivale a n>1 ? (n%d!=0 ? f(n, d+1) : d+f(n/d)) : n>1. In termini generali x and yè equivalente a x ? y : x. x and y or zè equivalente a x ? y : znella maggior parte dei casi.
Ovs,

1
@KevinCruijssen una porta Java sarebbe qualcosa di simile f=(n,d=2)->n>1?n%d>0?f(n,d+1):d+f(n/d):0.
Ovs

Ah ok. Grazie per la spiegazione, ora ha molto più senso. E ricordo di x and yessere stato anche x ? y : xda JavaScript. Grazie!
Kevin Cruijssen,

4

Java 8, 175 144 142 141 byte

n->{for(int i,t=n,x;;n=t){for(i=2;i<t;t=t%i++<1?0:t);if(t>1|n<5)return n;for(t=0,i=1;i++<n;)for(;n%i<1;n/=i,t+=x)for(x=i;x>9;x/=10)t+=x%10;}}

-1 byte grazie a @Nevay .

A differenza dei singoli byte in alcuni dei linguaggi del golf, Java è piuttosto prolisso per i primi controlli, i fattori primi, le somme delle cifre e così, quindi immagino che meno di 200 non siano troppo squallidi.
Molto probabilmente è ancora possibile giocare a golf combinando i loop e non usando un metodo ricorsivo separato per la somma delle cifre .

Spiegazione:

Provalo qui.

n->{                // Method with integer as both parameter and return-type
  for(int i,        //  Index-integer `i`
          t=n,      //  Temp integer `t`, starting at the input `n`
          x;        //  Temp integer `x`
      ;             //  Loop (1) indefinitely
      n=t){         //    After every iteration, replace `n` with the value `t`
    for(i=2;        //   Reset `i` to 2
        i<t;        //   Inner loop (2) from 2 to `t` (exclusive)
        t=t%i++<1?  //    If `t` is divisible by `i`:
           0        //     Set `t` to 0
          :         //    Else:
           t        //     Leave `t` the same
    );              //   End of inner loop (2)
    if(t>1          //   If `t` is not 0 (it means it's a prime),
       |n<5)        //   or if `n` is below 5 (for edge-cases `4` and 'prime' `1`)
      return n;     //    Return `n` as result
    for(t=0,        //   Reset `t` to 0
        i=1;        //   Reset `i` to 1
        i++<n;)     //   Inner loop (3) from 2 to `n` (inclusive)
      for(;n%i<1;   //    Inner loop (4) as long as `n` is divisible by `i`
          n/=i,     //      After every iteration: Divide `n` by `i`,
          t+=x)     //      and increase `t` by `x`
        for(x=i;    //     Reset `x` to `i`
            x>9;    //     Inner loop (5) as long as `x` contains more than 1 digit
            x/=10)  //       After every iteration, remove the trailing digit
          t+=n%10;  //      Increase `t` with the trailing digit of `n`
                    //     End of inner loop (5) (implicit / single-line body)
                    //    End of inner loop (4) (implicit / single-line body)
                    //   End of inner loop (3) (implicit / single-line body)
  }                 //  End of loop (1)
}                   // End of method

6
+1 per il disturbo di scrivere una spiegazione dettagliata come se fosse una lingua da golf.
mio pronome è monicareinstate il

@someone Grazie! Dato che qualcuno mi ha chiesto una spiegazione di una mia risposta Java una volta in passato, le ho aggiunte a tutte le mie risposte. :)
Kevin Cruijssen,

i,t=n,xsembra che appartenga a Python, ahah
ETHproductions

@ETHproductions Hehe, peccato che devo ancora aggiungere il comando int (a differenza di Python). ;)
Kevin Cruijssen,

Puoi usare i++<ninvece di ++i<=n.
Nevay,


3

Retina , 30 byte

{+`(\1|\b11+?\B)+$
$1;$#1$*
;

Input e output in unario .

Provalo online!(Esegue la conversione decimale / unaria per comodità.)

Spiegazione

{+`(\1|\b11+?\B)+$
$1;$#1$*

Il { istruisce Retina per eseguire l'intero programma in un ciclo finché un passaggio completo non riesce a modificare la stringa, cioè fino a raggiungere un punto fisso. Di conseguenza, il programma stesso calcola una fase della somma dei fattori primi del valore corrente.

Questa fase calcola la fattorizzazione primaria dell'input. L' +è simile a ) per assicurarsi che abbiamo catturato e divisore reale. Il vantaggio di usare questo approccio un po 'complicato è quel gruppo{ ma passanti solo questa fase fino all'arresto cambiando la stringa. Il regex cerca di abbinare la corsa finale di 1s abbinando ripetutamente la stessa sottostringa (cioè il fattore). Il modo in cui ciò viene fatto è un po 'contorto a causa del riferimento in avanti \1. Alla prima iterazione, il gruppo 1non ha ancora catturato nulla, quindi \1fallisce incondizionatamente. Invece, dobbiamo abbinare \b11+?\Bqual è la sottostringa più piccola possibile che inizia all'inizio della corsa, contiene almeno due 1se non copre l'intera corsa. Le iterazioni successive non saranno in grado di utilizzare nuovamente questa alternativa, a causa di \b. Quindi su tutte le ulteriori iterazioni, stiamo abbinando\1, cioè la stessa sottostringa più e più volte. Questo processo deve colpire esattamente la fine della stringa ( .$1 sarà stato usato esattamente n / d volte, cioè ciò che rimane dopo aver diviso il divisore d

Sostituiamo questa corrispondenza con d ( $1), una separazione ;e n / d ( $#1$*, che inserisce$#1 copie di 1, dove $#1è il numero di acquisizioni effettuate dal gruppo1 ).

Questo processo si interrompe quando l'esecuzione finale nella stringa è essa stessa un numero primo, perché quindi la regex non corrisponde più.

;

Tutto quello che dobbiamo fare per sommare i numeri primi è rimuovere tutti i separatori.


3

Ohm v2 , 4 byte

·ΘoΣ

Provalo online!

Spiegazione:

·Θ    evaluate the block until the result returned has already been seen
   Σ  sum
  o   the full prime factorization

2

In realtà , 7 byte

⌠w♂πΣ⌡Y

Provalo online!

Spiegazione:

⌠w♂πΣ⌡Y
⌠    ⌡Y  do this until output stops changing (fixed-point combinator)
 w         factor into [prime, exponent] pairs
  ♂π       product of each pair
    Σ      sum of products

2

R + pracma , 53 byte

function(n){for(i in 1:n)n=sum(pracma::factors(n))
n}

Provalo online! (R-violino)

R non ha un primi fattori di built-in, ma numerosi pacchetti ( pracma, numbers, ecc) fare, così ho preso una comoda breve.


1

Gelatina , 6 byte

Questa risposta utilizza uno dei tanti builtin di fattorizzazione primaria di Jelly e il veloce per repeat until the results are no longer unique.

ÆfSµÐL

Provalo online!


Penso che tu sia stato superato , ma, dato il tuo approccio, non sono sicuro che la risposta
funzioni

@cairdcoinheringaahing Ho appena controllato la sua risposta (o meglio, l'equivalente in Python) da 1 a 100000 e funziona. Penso che 1sia l'unico caso in cui il numero di passaggi necessari è uguale a n(il che va bene; con 1dobbiamo solo eseguirlo una volta), e non sembrano esserci casi in cui il numero di passaggi è maggiore di n(cioè non sembra esserci alcun controesempio). Ah bene, sono stato superato: D
Sherlock9

Beh, succede. Anche se +1 per essere lo stesso identico codice a cui ho pensato quando ho visto questa sfida
caird coinheringaahing

La somma dei fattori primi di n è sempre minore o uguale a n, il che rende abbastanza facile dimostrare che n è sempre più che sufficiente.
Chris,


1

PowerShell , 124 byte

function f($a){for($i=2;$a-gt1){if(!($a%$i)){$i;$a/=$i}else{$i++}}}
for($x=$args[0];$l-ne$x){$l=$x;$x=(f($x))-join'+'|iex}$x

Provalo online!

PowerShell non ha alcun fattore di fattorizzazione principale incorporato, quindi questo utilizza il codice della mia risposta su Prime Factors Buddies (la linea superiore) per eseguire i calcoli di fattorizzazione.

La seconda riga è la carne di questo programma. Prendiamo input da $argsin $x, quindi foreseguiamo il loop fino a$l è -not equal $x. (La prima iterazione, $lè $nulle$x è un numero intero, quindi eseguiremo il ciclo almeno una volta).

All'interno del loop, abbiamo impostato il nostro $l = $xper determinare se abbiamo raggiunto o meno la fine del loop. Quindi otteniamo i fattori di $xwith f($x), -joinquelli insieme a +e |iexloro (abbreviazione di Invoke-Expressione simili a eval). Viene archiviato nuovamente in $x. Pertanto, abbiamo raggiunto la "fine" in cui la scomposizione in fattori primi riassunti insieme è tornata a se stessa. Quindi, posizioniamo semplicemente $xsulla pipeline e l'output è implicito.


0

Mathematica, 35 byte

#//.x_:>Tr[1##&@@@FactorInteger@x]&

Provalo online!

(La matematica non supporta Tr. Devo implementarla manualmente)


4
1##&è l'abbreviazione di Timese FixedPointpuò quasi sempre essere abbreviata con //.:#//.x_:>Tr[1##&@@@FactorInteger@x]&
Martin Ender,

@MartinEnder Grazie! Avrei dovuto saperlo Times, ma non sapevo del FixedPointtrucco.
user202729

Il tuo codice è scritto in Mathematica. Questa non è una funzione matematica. Dovresti cambiare il nome della lingua in Mathematica o Tr in totale
J42161217

@ {nessuno} Siamo spiacenti, il nome della lingua (matematica) è stato un errore. {i cri evritime} ha risolto il problema.
user202729


0

Rubino , 63 byte

->n{n.times{n=n.prime_division.map{|x|x.reduce:*}.sum};n}

Provalo online!

Utilizza il -rprimeflag per +6 byte per utilizzare Prime # prime_division .

prime_divisionrestituisce coppie di [prime, exponent](ad esempio, per 24 abbiamo i fattori in [2, 2, 2, 3]modo che fornisca [[2, 3], [3, 1]]) quindi in ogni passaggio semplicemente moltiplichiamo i membri di quelle coppie e sommiamo i risultati.


0

Javascript (ES6), 63 byte

f=n=>(q=(p=(m,x)=>m<x?0:m%x?p(m,x+1):x+p(m/x,x))(n,2))^n?f(q):q
<input id=i type=number min=0 value=0 oninput="o.innerText=f(i.value)">
<p id=o></p>

Ungolfed:

f=n=>(                  // Recursive function `f`
    p=(m,x=2)=>(        //   Recursive function `p`, used to sum prime factors
        m<x?            //     If m (the number to be factored) is less than x (the current
            0           //     iteration), return 0
        :m%x?           //     Else if m doesn't divide x
            p(m,x+1)    //     run the next iteration
        :               //     Else (if m divides x)
            x+p(m/x,x)  //     Divide m by x and repeat the current iteration
    ),
    q=p(n),             //   Set q to the sum of the prime factors of n
    q^n?                //   If q != n then
        f(q)            //     repeat f with q
    :                   //   else
        q               //     return q
)

0

Java 8, 101 byte

n->{for(int i=n;i-->0;n=f(n,2));return n;}int f(int n,int d){return n>1?n%d>0?f(n,d+1):d+f(n/d,2):0;}

La straordinaria risposta di Python 2 di Port of @ovs .

Spiegazione:

Provalo qui.

n->{                  // Method with integer as both parameter and return-type
  for(int i=n;i-->0;  //  Loop the input amount of times
    n=f(n,2)          //   And change `n` that many times with a separate method call
  );                  //  End of loop
  return n;           //  Then return the integer `n` as result
}                     // End of method

int f(int n,int d){   // Separated method with 2 integer parameters and integer return-type
                      // (`d` is 2 when we initially call this recursive-method)
  return n>1?         //  If input `n` is larger than 1:
    n%d>0?            //   And it's not divisible by `d`:
     f(n,d+1)         //    Do a recursive-call with `n, d+1`
    :                 //   Else:
     d                //    Sum `d` with
      +f(n/d,2)       //    a recursive call with `n/d, 2`
   :                  //  Else:
    0;                //   Simply return 0
}                     // End of separated method
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.