Divisor suma de factorización de potencia primaria


11

La tarea es calcular la suma del divisor de un número dada su factorización prima.

Entrada

Dos matrices (o algo equivalente) de longitud n , una que contiene el factor primo y la otra que contiene el exponente correspondiente.

Salida

La suma de todos los divisores (incluido el número mismo).

Ejemplo

El número 240 tiene 2, 3 y 5 como factores primos con 4, 1 y 1 como los respectivos exponentes. La producción esperada sería entonces de 744.

Input: [2,3,5] [4,1,1]
Output: 744

Puntuación

¡El código más corto en bytes gana!

Si la complejidad del tiempo de ejecución de su solución es O (suma de exponentes) en lugar de O (producto de exponentes), su puntaje puede multiplicarse por 0.8.


Hubo una pregunta similar publicada aquí, pero no fue un desafío. Creo que el problema es lo suficientemente interesante como para jugar al golf.

El ganador será elegido este fin de semana.


¿La matriz de factores primos siempre tiene que ser primero y la matriz de exponentes segunda o podemos suponer que las matrices se ingresan al revés?
Sp3000

Puede asumir cualquier formato de entrada similar al propuesto
Moartem

No puedo encontrarlo en este momento, pero creo que esto o algo similar está en projecteuler.net
flawr

Respuestas:


3

Pyth, 13 bytes * 0.8 = 10.4

*Fms^LhdhedCQ

Demostración.

Esta respuesta funciona de manera algo diferente a las anteriores. Para calcular la suma de los factores de las potencias primarias del número, en lugar de usar una fórmula aritmética, los factores se construyen y se suman explícitamente.

Por ejemplo, en el par [privilegiada, exponente] [2, 4], hacemos un mapa 2 ^ xmás 0, 1, 2, 3, 4, dando [1, 2, 4, 8, 16], que se resume a continuación a 31.

Los resultados se multiplican y se imprimen.

Si la exponenciación se implementa correctamente, o si hay un almacenamiento intermedio de resultados, esto será O(sum of exponents).


Independientemente de la implementación, no creo que sea posible calcular la primera potencia n de a en O (n) tiempo, a menos que suponga que la multiplicación es O (1).
Dennis

@Dennis Bueno, los términos de orden superior dominan, por lo que probablemente tendría la rutina de la multiplicación de orden superior, que es O(n)si podemos suponer que la base es una constante.
isaacg

9

CJam, 15 bytes * 0.8 = 12

q~.{_@)#(\(/}:*

Pruébalo en línea . El orden de entrada es primero la lista de exponentes, luego la lista de primos (-3 bytes gracias a @Dennis) .

Para cada par primo-exponente (p, e)encuentre

(p^(e+1) - 1)/(p - 1)

luego encuentre el producto de todos estos. Por ejemplo, para 240 esto sería

(1 + 2 + 4 + 8 + 16)(1 + 3)(1 + 5) = 31 * 4 * 6 = 744

Dependiendo de cómo se implemente la exponenciación, esto puede ser mejor que O(sum of exponents).


6

APL, 18 13 bytes * 0.8 = 10.4

×/(1-⊣×*)÷1-⊣

Esto crea un tren de función diádica que toma la matriz de factores a la izquierda y los exponentes a la derecha.

×/             ⍝ Vector product of
  (1-⊣×*)      ⍝ each factor^(exponent+1)-1
         ÷1-⊣  ⍝ divided by factor-1

Pruébalo en línea . Tenga en cuenta que este es el mismo enfoque que la respuesta CJam increíblemente inteligente de Sp3000 .

¡Guardado 5 bytes gracias a Dennis!


2

TI-BASIC, 17 bytes * 0.8 = 13.6

También usa el método de Sp3000, aunque lo encontré de forma independiente. Toma una lista de Entrada y otra de la pantalla de inicio.

Input E
prod(AnsAns^∟E-1)/prod(Ans-1

Usar prod (dos veces es más pequeño porque nos permite usar el paréntesis abierto de forma gratuita. Tenga en cuenta que esta respuesta no admite matrices vacías, porque no hay matrices vacías en TI-BASIC.


2

Haskell, 38 * 0.8 = 30.4

product$zipWith(\p e->(p*p^e-1)/(p-1))

Uso:

product$zipWith(\p e->(p*p^e-1)/(p-1)) [2,3,5] [4,1,1]
744.0

La función anónima lleva (p,e)a la suma del divisor a p^etravés de la suma de series geométricas. Comprimir las dos listas con esto como unir y tomar el producto da el resultado.

No pude encontrar nada más corto que la expresión aritmética

(p*p^e-1)/(p-1)
sum$map(p^)[0..e]

Tal vez hay una manera de deshacerse de él (\p e->_).

La definición de la función Infix da la misma longitud (38):

p%e=(p*p^e-1)/(p-1)
product$zipWith(%)

2

C ++, 111 80 77 bytes * 0.8 = 61.6

int g(int*p,int*e,int n){return n?g(p+1,e+1,n-1)*(pow(*p,*e-1)-1)/(*p-1):1;}

Esto calcula (p ^ (e + 1) -1) / (p-1) y multiplica recursivamente todos los factores. Lo descubrí hace un año.

Gracias por ayudar, me olvidé por completo del uso booleano de estilo c ++.


1
n==0simplifica a !n- o podría revertir los resultados y simplemente usarn
Toby Speight

2

Matlab, 53

function t=f(x,y)
s=1:prod(x.^y);t=s*~mod(s(end),s)';

Ejemplo:

>> f([2 3 5], [4 1 1])
ans =
   744

Parece que puedes agregar la bonificación 0.8
Moartem

@Moartem ¡Gracias! Pero no estoy seguro de eso. Calculo el número sy luego pruebo todos los divisores posibles de 1a s. Entonces es (al menos) O (s), que probablemente esté entre O (suma de exponentes) y O (producto de exponentes)
Luis Mendo

Sí, es cierto, es incluso más grande que O (producto de exponentes)
Moartem

1

Python 2,156

from itertools import*
from operator import*
i=input()
print sum(reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]])))

Entrada

[[2,3,5],[4,1,1]]

Salida

744

Explicación

Este programa recibe una lista de 2 listas: factores y exponentes.

i=input() # Receive list of 2 lists: i[0] for factors i[1] for exponents

Luego, crea una lista de todas las combinaciones posibles de la lista de exponentes.

[x+1 for x in i[1]] # [4,1,1]->[5,2,2] (to include last element)
map(range,[x+1 for x in i[1]]) # [[0, 1, 2, 3, 4], [0, 1], [0, 1]]
product(*map(range,[x+1 for x in i[1]])) # [(0, 0, 0), (0, 0, 1), ..., (4, 1, 1)]

y comprimirlo con los factores:

zip(i[0],p) for p in product(*map(range,[x+1 for x in i[1]])) # [[(2, 0), (3, 0), (5, 0)], ..., [(2, 4), (3, 1), (5, 1)]]

Calcule los factores para la potencia de los exponentes:

 [a**b for a,b in zip(i[0],p)]for p in product(*map(range,[x+1 for x in i[1]])) # [[1, 1, 1], ..., [16, 3, 5]]

y multiplique cada lista (esto nos da todos los divisores):

reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]])) # [1, 5, 3, 15, ..., 240]

Finalmente, sume todas las listas e imprima:

print sum(reduce(mul,[a**b for a,b in zip(i[0],p)])for p in product(*map(range,[x+1 for x in i[1]]))) # 744

¿Podría explicar brevemente qué hace su código (ya que no estoy familiarizado con Python), para poder juzgar la complejidad de su código?
Moartem

Es un enfoque inteligente, pero la complejidad es el producto de los exponentes
Moartem

@Moartem Sí, no pasé mucho tiempo reduciendo la complejidad
TheCrypt

1

Pitón 3, 134 120 117

Entrada: dos matrices separadas por comas separadas por comas.

Ejemplo:

(2,3,7,11),(4,2,3,2)
21439600
from functools import*
a=eval(input())
print(reduce(int.__mul__,(sum(x**j for j in range(y+1))for x,y in zip(*a)),1))

Con NumPy se puede reducir a 100 bytes:

import numpy
a=eval(input())
print(numpy.product([sum(x**j for j in range(y+1))for x,y in zip(*a)]))

1
Para el primer ejemplo, para que lo sepas, en lugar de importar operatorpara usar muluna vez, puedes usar float.__mul__para guardar un montón de bytes.
Kade

1

Gelatina, no competidora

Esta respuesta no es competitiva, ya que el desafío es anterior a la creación de Jelly.

5 bytes (sin bonificación)

*PÆDS

Pruébalo en línea!

Cómo funciona

*PÆDS    Main link. Left input: p (prime factors). Right input: e (exponents).

*        Elevate the prime factors to the corresponding exponents.
 P       Take the product of all powers.
  ÆD     Find all divisors of the product.
    S    Compute the sum of the divisors.

7 bytes (5.6 bytes después de la bonificación)

*‘}’:’{P

Cómo funciona

×*’:’{P  Main link. Left input: p (prime factors). Right input: e (exponents).

 *       Elevate the prime factors to the corresponding exponents.
         This yields p ** e.
×        Multiply the prime factors with the corresponding powers.
         This yields p ** (e + 1).
  ’      Decrement the resulting products.
         This yields p ** (e + 1) - 1.
    ’{   Decrement the prime factors.
         This yields p - 1.
   :     Divide the left result by the right one.
         This yields (p ** (e + 1) - 1) / (p - 1).
      P  Take the product of all quotients.

Pruébalo en línea!


1

APL, 12 bytes * 0.8 = 9.6

×/1++/¨⎕*⍳¨⎕

Esto lee dos listas del teclado, los exponentes primero, es decir:

      ×/1++/¨⎕*⍳¨⎕
⎕:
      4 1 1
⎕:
      2 3 5
744

Explicación:

  • : leer una lista desde el teclado (los exponentes)
  • ⍳¨: para cada número en la lista, generar una lista [1..n].
  • ⎕*: lea otra lista desde el teclado (los números primos) y eleve cada primo a cada uno de los exponentes en las listas correspondientes
  • +/¨: suma cada lista
  • 1+: agregue uno a cada resultado, para compensar la falta x^0en cada una de las listas
  • ×/: tome el producto de los resultados

1

Raqueta (esquema), 65 * 0.8 = 52 bytes

La misma aritmética que todos los demás.

(λ(x y)(foldl(λ(m n o)(*(/(-(expt m(+ n 1))1)(- m 1))o))1 x y))

Explicación:

(λ (x y)    ;defines anonymous function with two inputs
    (foldl    ;recursively applies the following function to all elements of the lists given to an argument given (foldl function argument lists lists lists...)
        (λ (m n o) (* (/ (- (expt m (+ n 1)) 1) (- m 1)) o))    ;an anonymous function representing the same arithmetic used in the CJam answer, then multiplying it with our incrementor
        1 x y))    ;the incrementor argument is 1, and the input lists are the ones provided into the original function

0

Python 2, 80 Bytes * 0.8 = 64

Esto supone que la entrada viene una tras otra. Sigue la misma fórmula que se describe en la respuesta CJam de Sp3000.

print(reduce(float.__mul__,[~-(x**-~y)/~-x for x,y in zip(input(),input())],1)) 

Si esto no está permitido, lo usaré como una solución, que obtiene una puntuación de 84 bytes * 0.8 = 67.2. La entrada debe estar separada por una coma, es decir [2,3,5],[4,1,1].

k=input()
print(reduce(float.__mul__,[~-(x**-~y)/~-x for x,y in zip(k[0],k[1])],1))

Psst. ¡Oye! Esta es una posible solución en Symbolic, algo en lo que estoy trabajando:Ƥ(П([~-(x**-~y)/~-xϝx,yϊʐ(Ί,Ί)],1))


0

Mathematica, 40 bytes

Total[Outer@@{*}~Join~(#^0~Range~#2),3]&

Sin usar ninguno de los inbuilts que tratan con divisores, para diferenciar de la otra solución matemática en el hilo.

La entrada es (usando el ejemplo) [{2, 3, 5}, {4, 1, 1}]


0

Perl 5, 96 bytes

Obviamente esto no es ganador, pero decidí escribirlo por diversión.

Es una subrutina:

{($b,$e)=@_;$s=1;map$s*=$b->[$_]**$e->[$_],0..@$b-1;$_=1x$s;for$j(1..$s){$i+=$j*/^(.{$j})*$/}$i}

Véalo en acción así:

perl -e'print sub{...}->([2,3,5],[4,1,1])'

Cómo funciona:

  • ($b,$e)=@_lee los arrays de entrada $b(bases) y $e(exponentes).
  • $s=1 Inicializa el producto.
  • map$s*=$b->[$_]**$e->[$_],0..@$b-1multiplica $spor sucesivas potencias de exponente base. Ahora $ses el número compuesto.
  • $_=1x$sconjuntos $_iguales a una cadena de unos, $slargos. $ise inicializa en 0.
  • for$j(1..$s){$i+=$j*/^(.{$j})*$/}intenta, para cada número $jentre 1 y $s, dividirse $_como $jcaracteres repetidos cualquier cantidad de veces. Si puede, entonces se $jdivide $s, y /^(.{$j})*$/es 1 (de lo contrario es 0), y $ise aumenta por $j. Por lo tanto, agregamos al $inúmero de particiones en una partición de igual tamaño $_. Como señala Omar E. Pol , $ies el número que estamos buscando.
  • $iAl final vuelve $i.

0

J, 14 bytes * 0.8 = 11.2

[:*/(^>:)%&<:[

Uso

   f =: [:*/(^>:)%&<:[
   2 3 5 f 4 1 1
744
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.