Raíces factorales primarias

14

Inspirada en las raíces digitales, la raíz factoral principal de un número es el número que emerge cuando tomas los factores primos de un número, los sumas y repites el proceso en el número resultante, continuando hasta que terminas con un número primo ( que se tiene a sí mismo como su único factor primo y, por lo tanto, es su propia raíz factoral primaria). La raíz factoral primaria de 4 es 4, ya que 2 * 2 = 2 + 2, y esta es la única raíz factoral prima no prima de un entero mayor que 1 (que es otro caso especial, ya que no tiene factores primos). La secuencia OEIS formada por raíces factoras primarias es A029908 .

Por ejemplo, la raíz factoral principal de 24 es:

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.  

Tu tarea:

Escriba un programa o función que encuentre la raíz factoral principal de un entero de entrada.

Entrada:

Un número entero, ingresado a través de cualquier método razonable, entre 2 y el número entero más grande que admitirá su idioma (inclusive). Específicamente, no está permitido elegir un idioma que tenga un tamaño entero máximo irrazonablemente bajo (y también viola este vacío legal estándar )

Salida:

Un número entero, la raíz factoral principal de la entrada.

Casos de prueba:

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

Puntuación:

Este es el , ¡la puntuación más baja en bytes gana!

Grifo
fuente
3
¿Puede agregar 4en los casos de prueba, ya que es una excepción y es fácil olvidarlo mientras prueba una respuesta?
scottinet
¿Tenemos que dar salida 1 por 1?
mi pronombre es monicareinstate
@someone de acuerdo con la secuencia OEIS vinculada, debería generar 0 por 1
scottinet
2
@someone El desafío indica que la entrada será al menos 2.
Martin Ender
@ Alguien Perdón por estar fuera por un tiempo. Como dijo Martin, el desafío dice específicamente que la entrada será mayor que uno y, por lo tanto, el comportamiento cuando la entrada es 1 no está definido.
Gryphon

Respuestas:

15

05AB1E , 3 bytes

FÒO

Pruébalo en línea!

Explicaciones:

FÒO   
F    Loops <input> times + 1
 Ò   List of prime factors w/ duplicates
  O  Total sum of the list
     -- implicit output
scottinet
fuente
Esto parece fallar por 4.
Shaggy
1
@Shaggy corregido al guardar 2 bytes
scottinet
10
¿Esto hace que alguien que intente vencer a este sea un luchador FÒO?
steenbergh
Al menos no era FOObar.
Urna mágica del pulpo
14

Haskell , 61 bytes

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

Pruébalo en línea!

Explicación

until=<<((==)=<<)toma una función fy la aplica a la entrada xhasta que se alcanza un punto fijo, que es f xigual x. primeFactorsdevuelve la lista de factores primos de un número, sumproduce la suma de una lista de números.

Pero espera, ¿por qué until=<<((==)=<<) el trabajo y se ve tan raro?

Si suponemos f=sum.primeFactors, una definición más natural sería until(\x->f x==x)f, porque untiltoma un predicado (una función que devuelve un valor booleano), una función que tiene el mismo tipo de entrada y retorno (por ejemplo Int -> Int) y valor de este tipo, y luego aplica la función al valor hasta que se cumpla el predicado.

until(\x->f x==x)fes lo mismo que until(\x->(==)(f x)x)f, y como sostiene que g (h x) xes lo mismo que (g=<<h)x, obtenemos until(\x->((==)=<<f)x)f. Después de la conversión Eta , esto se convierte until((==)=<<f)f. Pero si ahora tratamos (==)=<<como una función que se aplica a f, podemos ver que until(((==)=<<)f)fes de nuevo de la forma g (h x) x, con g=until, h=((==)=<<)y x=f, por lo que se puede reescribir a (until=<<((==)=<<))f. Usando el $operador para deshacerse de los paréntesis externos y sustituyéndolos fcon sum.primeFactorsla solución de arriba.

Laikoni
fuente
44
=<<((==)=<<)$Whaaaaaat.
Totalmente humano
2
@icrieverytim Agregué una explicación. No dude en preguntar en la sala de chat de Haskell si tiene más preguntas sobre cómo funciona esta brujería.
Laikoni
5

Casco , 4 bytes

ω(Σp

Pruébalo en línea!

Explicación:

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

Pyth , 3 bytes

usP

Pruébalo aquí.

Explicación:

usPGQ The trailing GQ is implicit
  PG  Get prime factors
 s    Sum
u   Q Repeat until returned value no longer unique starting with the input
Erik el Outgolfer
fuente
¿Olvidaste actualizar tu explicación?
MCMastery
1
@MCMastery No, el código y la explicación son los mismos. The trailing GQ is implicit
Totalmente humano el
@MCMastery lo que dije cada vez que decía
Erik the Outgolfer el
4

Python 2 , 84 bytes

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

Pruébalo en línea!

ovs
fuente
Esta puede ser una pregunta bastante tonta, pero ¿cómo f=lambda n,d=2:n>1and(n%d and f(n,d+1)or d+f(n/d))funciona? Nunca he programado en Python (principalmente Java y C #), así que no estoy seguro de cuál es el resultado de esta función. ¿Esta función modifica la entrada ny la devuelve después, o es similar a un booleano donde n>1and(n%d and f(n,d+1)or d+f(n/d))es 0 o 1, o 0 o n, o algo más? Estoy tratando de visualizar cómo se vería un puerto de esto en Java / C #, pero no puedo porque realmente no entiendo Python lambdas como este en general.
Kevin Cruijssen
1
@KevinCruijssen esto es equivalente a n>1 ? (n%d!=0 ? f(n, d+1) : d+f(n/d)) : n>1. En términos generales x and yes equivalente a x ? y : x. x and y or zes equivalente a x ? y : zen la mayoría de los casos.
ovs
1
@KevinCruijssen un puerto Java sería algo así f=(n,d=2)->n>1?n%d>0?f(n,d+1):d+f(n/d):0.
ovs
Ah ok Gracias por la explicación, ahora tiene mucho más sentido. Y recuerdo x and yser x ? y : xde JavaScript también. ¡Gracias!
Kevin Cruijssen
4

Java 8, 175 144 142 141 bytes

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 gracias a @Nevay .

A diferencia de los bytes individuales en algunos de los lenguajes de golf, Java es bastante detallado para verificaciones primas, factores primos, sumas de dígitos y demás, por lo que supongo que menos de 200 no está nada mal.
Lo más probable es que se pueda jugar golf combinando bucles y no utilizando un método recursivo separado para la suma de dígitos .

Explicación:

Pruébalo aquí.

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
Kevin Cruijssen
fuente
66
+1 por molestarse en escribir una explicación tan detallada como si fuera un lenguaje de golf.
mi pronombre es monicareinstate
@ alguien Gracias! Como alguien me preguntó acerca de una explicación de una respuesta mía de Java una vez en el pasado, las he agregado a todas mis respuestas. :)
Kevin Cruijssen
i,t=n,xparece que pertenece a Python, jaja
ETHproductions
@ETHproductions Jeje, lástima que todavía tengo que agregar el líder int (a diferencia de Python). ;)
Kevin Cruijssen
Puedes usar en i++<nlugar de ++i<=n.
Nevay
3

Retina , 30 bytes

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

Entrada y salida en unario .

Pruébalo en línea! (Realiza conversión decimal / unaria por conveniencia).

Explicación

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

Le {indica a Retina que ejecute todo el programa en un bucle hasta que un paso completo no pueda modificar la cadena, es decir, hasta que se alcance un punto fijo. En consecuencia, el programa mismo calcula un paso para sumar los factores primos del valor actual.

Esta etapa misma calcula la factorización prima de la entrada. El +es similar a {pero realiza un bucle solo en esta etapa hasta que deja de cambiar la cadena. La expresión regular intenta hacer coincidir la ejecución final de 1s haciendo coincidir repetidamente la misma subcadena (es decir, el factor). La forma en que se hace esto es un poco complicada debido a la referencia directa \1. En la primera iteración, el grupo 1aún no ha capturado nada, por lo que \1falla incondicionalmente. En cambio, tenemos que hacer coincidir \b11+?\Bcuál es la subcadena más pequeña posible que comienza al comienzo de la ejecución, contiene al menos dos 1sy no cubre la ejecución completa. Las iteraciones posteriores no podrán volver a utilizar esta alternativa debido a \b. Entonces, en todas las iteraciones posteriores, estamos haciendo coincidir\1, es decir, la misma subcadena una y otra vez. Este proceso tiene que llegar al final de la cadena exactamente ( $) para asegurarse de que hayamos capturado y divisor real. El beneficio de utilizar este enfoque algo complicado es que el grupo 1se habrá utilizado exactamente n / d veces, es decir, lo que queda después de dividir el divisor d .

Reemplazamos esta coincidencia con d ( $1), una separación ;y n / d ( $#1$*, que inserta $#1copias de 1, donde $#1es el número de capturas realizadas por grupo 1).

Este proceso se detiene una vez que la ejecución final en la cadena es en sí misma un primo, porque la expresión regular ya no coincide.

;

Todo lo que necesitamos hacer para sumar los números primos es eliminar todos los separadores.

Martin Ender
fuente
3

Ohm v2 , 4 bytes

·ΘoΣ

Pruébalo en línea!

Explicación:

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

En realidad , 7 bytes

⌠w♂πΣ⌡Y

Pruébalo en línea!

Explicación:

⌠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
Mego
fuente
2

R + pracma , 53 bytes

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

Pruébalo en línea! (violín r)

R no tiene una orden interna factores primos, pero numerosos paquetes ( pracma, numbers, etc.) hacer, así que cogí un convenientemente corta.

Giuseppe
fuente
1

Jalea , 6 bytes

Esta respuesta utiliza una de las muchas incorporaciones de factorización primarias de Jelly, y la rápida repeat until the results are no longer unique.

ÆfSµÐL

Pruébalo en línea!

Sherlock9
fuente
Creo que te han superado pero, dado tu enfoque, no estoy seguro de si esa respuesta funciona
caird coinheringaahing
@cairdcoinheringaahing Acabo de verificar su respuesta (o más bien, el equivalente de Python) de 1 a 100000 y funciona. Creo que 1es el único caso en el que la cantidad de pasos necesarios es igual a n(lo cual está bien; 1solo tenemos que ejecutarlo una vez), y no parece haber ningún caso en el que la cantidad de pasos sea mayor que n(es decir no parece haber ningún contraejemplo). Ah bueno, me han superado: D
Sherlock9
Bueno, eso pasa. Aunque +1 por ser exactamente el mismo código en el que pensé cuando vi este desafío
caird coinheringaahing
La suma de los factores primos de n siempre es menor o igual que n, lo que hace que sea bastante fácil demostrar que n siempre es más que suficiente.
Chris
1

MATL , 6 bytes

Utiliza la idea de scottinet de recorrer más veces de lo necesario. Gracias también a Shaggy por señalar un error, ahora corregido.

t:"Yfs

Pruébalo en línea!

Explicación

t       % Take input (implicit). Duplicate
:"      % Do the following that many times
  Yf    %   Array of prime factors
  s     %   Sum of array
        % End (implicit). Display (implicit)
Luis Mendo
fuente
Esto parece fallar por 4.
Shaggy
@ Shaggy Gracias! Trabajando en ello
Luis Mendo
@Shaggy Resuelto ahora
Luis Mendo
1

PowerShell , 124 bytes

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

Pruébalo en línea!

PowerShell no tiene incorporados factores de factorización primos, por lo que utiliza el código de mi respuesta en Prime Factors Buddies (la línea superior) para realizar los cálculos de factorización.

La segunda línea es la carne de este programa. Tomamos el aporte de $argsen $x, a continuación, forbucle hasta que $les -not equal a $x. (La primera iteración $les $nully $xes un número entero, por lo que realizaremos un bucle al menos una vez).

Dentro del bucle, establecemos nuestro $l = $xpara determinar si hemos llegado al final del bucle o no. Entonces se obtienen los factores de $xla f($x), -joinlos, junto con +y |iexellos (la abreviatura deInvoke-Expression y similares a eval). Eso se almacena de nuevo en $x. Por lo tanto, hemos llegado al "final", donde la factorización prima sumada es volver a sí misma. Luego, simplemente colocamos $xen la tubería y la salida es implícita.

AdmBorkBork
fuente
0

Mathematica, 35 bytes

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

Pruébalo en línea!

(Las matemáticas no son compatibles Tr. Tengo que implementarlo manualmente)

usuario202729
fuente
44
1##&es la abreviatura Timesy FixedPointcasi siempre se puede acortar con //.:#//.x_:>Tr[1##&@@@FactorInteger@x]&
Martin Ender
@MartinEnder Gracias! Ya debería haber sabido Times, pero no he sabido sobre el FixedPointtruco.
user202729
Su código está escrito en Mathematica. Esta no es una función matemática. Debe cambiar el nombre del idioma a Mathematica o Tr a Total
J42161217
@ {nadie} Lo sentimos, el nombre del idioma (matemáticas) fue un error. {i cri evritime} arregló eso.
user202729
0

Ruby , 63 bytes

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

Pruébalo en línea!

Utiliza el -rprimeindicador de +6 bytes para utilizar Prime # prime_division .

prime_divisiondevuelve pares de [prime, exponent](por ejemplo, para 24 tenemos los factores [2, 2, 2, 3]por lo que da [[2, 3], [3, 1]]) así que en cada paso simplemente multiplicamos los miembros de esos pares y sumamos los resultados.

Bocadillo
fuente
0

Javascript (ES6), 63 bytes

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>

Sin golf:

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
)
Herman L
fuente
0

Java 8, 101 bytes

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 sorprendente respuesta de Python 2 de @ovs .

Explicación:

Pruébalo aquí.

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
Kevin Cruijssen
fuente