Mayor número en un rango cuando se resta la suma de los cuadrados de sus factores primos

17

La formula

Tomemos por ejemplo el número 300

  • Los factores primos de 300 son [2, 3, 5](números únicos que son factores de 300 y primos)
  • Cuadrar cada uno de esos números te dará [4, 9, 25]
  • Sumar esa lista te dará 4 + 9 + 25 = 38
  • Finalmente reste esa suma (38) de su número original 300-38 = 262(este es el resultado)

Entrada

Su entrada será un número entero positivo mayor que 2. Debe verificar todos los números del 2 al valor de entrada (inclusive) y encontrar el número que produce el mayor resultado con la fórmula anterior.


Salida

Su salida será dos números separados por un espacio, una coma, una nueva línea o lo que su idioma permita (la separación es necesaria para distinguir los dos números). Estos pueden enviarse a un archivo, stdout o lo que sea que use su idioma. Su objetivo es encontrar el número en el rango que produce la salida máxima cuando se ejecuta la fórmula anterior. El primer número que se muestra debe ser el número inicial (como 300) y el segundo número debe ser el resultado que produjo la fórmula (como 262)


Casos de prueba

Input: 3       Output: 2, -2
Input: 10      Output: 8, 4
Input: 50      Output: 48, 35
Input: 1000    Output: 1000, 971
Input: 9999    Output: 9984, 9802


Trabajado a través del ejemplo

Considere la entrada de 10, debemos ejecutar la fórmula para todos los números del 2 al 10 (inclusive)

Num PrimeFacs PrimeFacs^2 SumPrimeFacs^2 Result
2   [2]       [4]         4              -2
3   [3]       [9]         9              -6
4   [2]       [4]         4               0
5   [5]       [25]        25             -20
6   [2, 3]    [4, 9]      13             -7
7   [7]       [49]        49             -42
8   [2]       [4]         4               4
9   [3]       [9]         9               0
10  [2, 5]    [4, 25]     29             -19

Como puede ver, el mejor resultado es el 4resultado de ingresar el valor 8en la fórmula. Eso significa la salida para una entrada de10 debería ser8, 4


Puntaje y Reglas

Se aplican las reglas predeterminadas para entradas y salidas: Predeterminado para Code Golf: Métodos de entrada / salida
Las lagunas estándar están prohibidas: Lagunas que están prohibidas por defecto
presentaciones pueden ser funciones o programas completos

El código más corto en bytes gana

Keatinge
fuente
He corregido algunos errores ortográficos y gramaticales, e hice el título más descriptivo. También cambié un poco sobre deshabilitar los separadores de espacios en blanco, ya que eso claramente no es lo que querías decir (ya que las líneas nuevas y los espacios son caracteres de espacios en blanco). Si esto no es lo que pretendía, no dude en revertir la edición y aclarar su intención.
Mego
2
¿Qué debería suceder si varios números están empatados para el resultado máximo?
Dennis
1
@ Dennis, ¿es aceptable para mí permitir que sea cualquier número que genere el máximo resultado? No quiero imponer una nueva regla que rompa todas las soluciones existentes.
Keatinge
2
Sí, esa es probablemente la mejor opción. 950 podría ser un ejemplo, donde [900, 862] y [945, 862] serían respuestas válidas.
Dennis
1
La salida puede que los números en orden inverso, por ejemplo para la entrada 50: 35, 48?
nimi

Respuestas:

4

Java 8 lambda, 247 239 233 225 224 219 198 161 caracteres

Pensé que debía ser posible en menos de 300 caracteres porque ... ya sabes ... ¡Java!

¡Y de hecho es posible incluso en menos de 200 caracteres!

m->{int n=1,u,f,F[],g,G=g=1<<31;for(;++n<=m;){u=n;F=new int[m+1];for(f=1;++f<=u;)u/=u%f<1?(F[f]=f--):1;f=0;for(int p:F)f+=p*p;g=n-f>g?(G=n)-f:g;}return G+","+g;}

No sé si este uso de las importaciones es legítimo, pero supongo que debería estar bien. Aquí está la lambda sin golfista en una clase:

public class Q80507 {
    static String greatestAfterReduction(int maxNumber) {
        int number = 1, upper, factor, primeFactors[], greatestResult, greatestNumber = greatestResult = 1 << 31; // <-- Integer.MIN_VALUE;
        for (;++number <= maxNumber;) {
            // get unique primefactors
            upper = number;
            primeFactors = new int[maxNumber + 1];
            for (factor = 1; ++factor <= upper;)
                upper /= upper % factor < 1 ? (primeFactors[factor] = factor--) : 1;

            factor = 0;
            for (int prime : primeFactors)
                factor += prime * prime;

            greatestResult = number - factor > greatestResult ? (greatestNumber = number) - factor : greatestResult;
        }
        return greatestNumber + "," + greatestResult;
    }
}

El hallazgo de factores primos se basa en esta respuesta . El código utiliza la funcionalidad de los conjuntos, ya que solo guardan cada valor una vez, por lo que no tengo que preocuparme por los duplicados agregados más adelante. El resto del código es bastante sencillo, solo sigue la pregunta.

Actualizaciones

Se eliminó la nueva línea de la salida.

Gracias a @ogregoire por jugar al golf Integer.MIN_VALUE a 1 << 31!

Después de buscar el código nuevamente, encontré algunos lugares más donde las cosas podían jugar golf.

¡Gracias a @Blue por el truco == 0 a <1!

Se eliminaron algunos espacios en blanco sobrantes. Además, para la separación solo se necesita un carácter, por lo que no es necesario desperdiciar un carácter.

¡Gracias nuevamente a @ogregoire por señalar que puedo devolver el valor en lugar de imprimirlo y armar las declaraciones! Esto ahorró mucho!

Descubrí que puedo usar un ternario en lugar del segundo si para guardar un personaje más.

Gracias a @AstronDan por el increíble uso de una matriz que guarda la importación. Eso también me dio la posibilidad de acortar el primero si es ternario.

Frozn
fuente
1
Integer.MIN_VALUEse puede acortar como 1<<31.
Olivier Grégoire
1
Ahorre 1 bytes con if (u% f <1) en su lugar
Azul
1
Declare todos sus correos electrónicos inten el mismo lugar para evitar repetirlos intvarias veces y asígneles su valor allí si es posible.
Olivier Grégoire
1
Además, deshágase de eso System.out.println(...)y devuelva un valor en lugar de imprimirlo: como el OP menciona, el método estándar de E / S está en uso.
Olivier Grégoire
1
También puede usar el truco de matriz que usé en C # para convertir el hashset en una matriz int. Esto probablemente le permitirá eliminar la importación ahorrando muchos bytes.
AstroDan
3

En realidad, 21 bytes

u2x;`;y;*@-`M;M;)@í@E

Pruébalo en línea!

Explicación:

u2x;`;y;*@-`M;M;)@í@E
u2x;                   push two copies of range(2, n+1) ([2, n])
    `      `M          map:
     ;                   duplicate
      y;                 push two copies of prime divisors
        *                dot product of prime divisors lists (equivalent to sum of squares)
         @-              subtract from n
             ;M;)      duplicate, two copies of max, move one copy to bottom of stack
                 @í    get index of max element
                   @E  get corresponding element from range
Mego
fuente
¿Puedes enlazar a este idioma?
No es que Charles
1
@NotthatCharles Puede hacer clic en el nombre del idioma en el intérprete en línea.
Dennis
Ok, busqué en Google Actually Programming Languagey no encontré nada incluso después de navegar por la quinta página de resultados de Google. ¿Que idioma es este?
Tejas Kale
2
@Tejas Puede hacer clic en el nombre del idioma que lo enviaría a su fuente: github.com/Mego/Seriously
Amndeep7
3

MATL , 18 bytes

:"@tYfu2^s-]v2#X>w

Pruébalo en línea!

El último caso lleva demasiado tiempo para el compilador en línea, pero produce el resultado correcto (tarda unos 11 segundos en mi computadora, ejecutándose en Matlab):

ingrese la descripción de la imagen aquí

Explicación

Aplicación directa del procedimiento descrito.

:         % Implicit input n. Range [1 2 ... n]
"         % For each
  @       %   Push that number
  tYfu    %   Duplicate. Prime factors. Unique values
  2^s-    %   Square. Sum of array values. Subtract
]         % End for each
v         % Concatenate stack contents into vertical vector
2#X>      % Max and arg max
w         % Swap. Implicit display         
Luis Mendo
fuente
3

C #, 194 bytes

Mi primer código de golf :). Usé mi idioma favorito a pesar de su verbosidad. Comencé esto como un puerto de función C # de Java de @ Frozn, pero encontré varias formas de reducir aún más el código con optimizaciones.

string R(int a){int u,f,g,N=g=1<<31;for(int n=1;++n<=a;){u=n;int[]P=new int[a+1];for(f=1;++f<=u;){if(u%f<1){u/=f;P[f]=f--;}}f=0;foreach(var p in P){f+=p*p;}if(n-f>g){g=(N=n)-f;}}return N+","+g;}

Esto usa una matriz para almacenar los factores primos. Debido a que está indexado por el factor, reemplazará los factores repetidos con copias del factor. Esto permite que la función no tenga importaciones. Esto ni siquiera requiere sistema.

AstroDan
fuente
¡Este es un truco REALMENTE agradable! Intentaré usarlo en mi versión
Frozn
3

Bash + utilidades GNU, 74

seq 2 $1|factor|sed -r 's/:?( \w+)\1*/-\1*\1/g'|bc|nl -v2|sort -nrk2|sed q
  • seq genera todos los enteros 2 a n
  • factorda el número seguido de dos puntos, luego una lista separada por espacios de todos los factores primos, incluidos los duplicados. por ejemplo, el resultado para 12 es12: 2 2 3
  • sedelimina los dos puntos y los factores duplicados, luego genera la expresión aritmética requerida. por ejemplo para 12:12- 2* 2- 3* 3
  • bc evalúa esto
  • nl prefijos n de nuevo (a partir de 2)
  • sort por la segunda columna, numéricamente, en orden descendente
  • seq imprime la primera línea y se cierra.

Ideona

Trauma digital
fuente
2

Brachylog , 48 bytes

:2:{eI$pd:{:2^.}a+:I--:I.}fF$\hor:0m:Ir.r~m[F:J]

Explicación

Main predicate:

:2:{}fF                     Unify F with the list of all binding for which predicate 1 is
                            true, given [Input, 2] as input.
       $\hor:0m             Retrieve the max of F by diagonalizing it, taking the
                            first row, sorting that row and reversing the sorted row.
               :Ir.         Unify the Output with [I, Max],
                   r~m[F:J] [I, Max] is in F at index J (the index is unimportant)


Predicate 1:

eI                          I is an integer in the range given in Input
  $pd                       Get the list of prime factors of I, with no duplicates
     :{:2^.}a               Apply squaring to each element of that list
             +              Sum the list
              :I-           Subtract I from the sum
                 -          Multiply by -1 (let's call it Result)
                  :I.       Unify the Output with [Result, I]
Fatalizar
fuente
2

Jalea , 13 bytes

ÆfQ²S_@,µ€ḊṀṚ

Pruébalo en línea! o verificar todos los casos de prueba .

Cómo funciona

ÆfQ²S_@,µ€ḊṀṚ  Main link. Argument: n

        µ      Combine the chain to the left into a link.
         €     Apply it to each k in [1, ..., n].
Æf               Yield k's prime factors as a list.
  Q              Unique; deduplicate the prime factors.
   ²             Square each unique prime factor.
    S            Compute their sum.
     _@          Subtract the result from k.
       ,         Pair with k, yielding [result(k), k].
          Ḋ    Dequeue; discard the first pair which corresponds to k = 1.
           Ṁ   Get the maximum (lexicographical order).
            Ṛ  Reverse the pair.
Dennis
fuente
2

05AB1E, 19 17 16 bytes

Código:

L©f€n€O®-®)ø¦{¤R

Explicación:

L                    # make a list of 1..input [1,2,3,4,5,6]
 ©                   # save the list for reuse
  f                  # get primefactors of numbers in list [[],[2],[3],[2],[5],[2,3]]
   €n                # square each factor [[],[4],[9],[4],[25],[4,9]]
     €O              # sum the factors [0,4,9,4,25,13]
       ®-            # subtract from saved list [1,-2,-6,0,-20,-7]
         ®)ø         # zip with saved list [[1,1],[-2,2],[-6,3],[0,4],[-20,5],[-7,6]]
            ¦        # drop the first item (n=1) [[-2,2],[-6,3],[0,4],[-20,5],[-7,6]]
             {       # sort [[-20,5],[-7,6],[-6,3],[-2,2],[0,4]]
              ¤      # get last item [0,4]
               R     # reverse [4,0]

Pruébalo en línea

Emigna
fuente
2

Julia, 56 bytes

!n=maximum(k->(k-sumabs2(k|>factor|>keys),k),2:n)[[2,1]]

Pruébalo en línea!

Cómo funciona

Dada una entrada n , para cada entero k tal que 2 ≤ k ≤ n , generamos la tupla (f (k), k) , donde f (k) es la diferencia entre k y la suma de los cuadrados de sus factores primos .

f (k) se calcula con k-sumabs2(k|>factor|>keys), que factoriza k en un Dict de claves primas y valores de exponente, extrae todas las claves (factores primos), toma la suma de sus cuadrados y resta el entero resultante de k .

Finalmente, tomamos el máximo lexicográfico de las tuplas generadas y lo invertimos accediendo a él en los índices 2 y 1 .

Dennis
fuente
1

Clojure, 215 bytes

(fn j[x](apply max-key second(map(fn[w][w(- w(let[y(reduce +(map #(* % %)(set(flatten((fn f[q](let[c(filter(fn[r](=(mod q r)0))(range 2 q))](if(empty? c)q(map f c))))w)))))](if(= y 0)(* w w)y)))])(range 2(inc x)))))

Solo sigue las reglas. Calcula los factores primos de cada número, los pone al cuadrado y los suma. Después de eso, genere una lista de vectores de 2 elementos: número inicial y su resultado y encuentre el elemento con el valor máximo del segundo elemento.

Puede verlo en línea aquí: https://ideone.com/1J9i0y

acantilado
fuente
1

R 109 bytes

y=sapply(x<-2:scan(),FUN=function(x)x-sum(unique(as.numeric(gmp::factorize(x))^2)));c(x[which.max(y)],max(y))

Hice trampa y se utiliza un paquete, gmp.

bola hinchable
fuente
1

PowerShell v2 +, 124 120 117 bytes

2..$args[0]|%{$y=$z=$_;2..$_|%{$y-=$_*$_*!($z%$_)*('1'*$_-match'^(?!(..+)\1+$)..')};if($y-gt$o){$o=$y;$p=$_}}
"$p $o"

La primera línea calcula los valores, la segunda es solo salida.

Comenzamos con la creación de un rango de 2hasta nuestro argumento de línea de comandos $args[0]y lo repetimos |%{...}. En cada ciclo establecemos variables auxiliares iguales a nuestro valor actual $y=$z=$_. Luego recorremos cada número desde 2hasta nuestro número actual. Cada ciclo interno verificamos si ese número es un divisor !($z%$_)y si es primo ('1'*$_-match'^(?!(..+)\1+$)..') , y si es ambos, restamos el cuadrado de $y(las verificaciones se realizan mediante la multiplicación booleana).

Una vez que pasamos por todos los divisores primos y restamos los cuadrados, si el número restante es el más grande que hemos visto hasta ahora $y-gt$o, establecemos nuestras variables de salida $o=$y;$p=$_. Después de recorrer todo el rango, simplemente salimos con un espacio entre ellos.

AdmBorkBork
fuente
1

Haskell, 91 bytes

f m=reverse$maximum[[n-sum[p^2|p<-[2..n],mod n p<1,mod(product[1..p-1]^2)p>0],n]|n<-[2..m]]

Ejemplo de uso: f 50->[48,35] .

Las funciones de factores primos solo están disponibles a través de las import Data.Numbers.Primescuales cuesta demasiados bytes, por lo que estoy usando el verificador principal de @ Lynn . El resto es sencillo: para la entrada de mbucle na través de [2..m]y en un bucle interior pa través [2..n]. Mantenga todo lo pque es primo y divida n, cuadrado y suma.

nimi
fuente
1

Python 2, 108 105 100 bytes

f=lambda n,m=2,p=1:m>n or-~f(n,m+1,p*m*m)-(n%m<p%m)*m*m
r=max(range(2,input()+1),key=f)
print r,f(r)

Pruébalo en Ideone .

Dennis
fuente
1

JavaScript (ES6), 111105 bytes

f=n=>{r=n<2?[]:f(n-1);for(s=[],j=n,i=2;j>1;k%i?i++:j/s[i]=i);s.map(i=>j-=i*i,j=n);return j<r[1]?r:[n,j]}

No tengo idea de por qué no pensé hacer esto recursivamente antes.

Neil
fuente
1

J, 44 bytes

[:((],.~2+I.@e.)>./)@:}.1(-[:+/*:@~.@q:)@+i.

Enfoque directo. También devuelve todos los valores de nese resultado en un valor máximo.

Uso

   f =: [:((],.~2+I.@e.)>./)@:}.1(-[:+/*:@~.@q:)@+i.
   f 3
2 _2
   f 10
8 4
   f 50
48 35
   f 1000
1000 971
   f 9999
9984 9802
   f 950
900 862
945 862
millas
fuente