Encuentra la suma de los divisores de N

20

Escriba un programa que muestre en la pantalla la suma de los divisores de un número (1 ≤ N ≤ 100) ingresado por el usuario en el rango de 1 a N.

Este es OEIS A000203 .


Ejemplos:

Entrada : 7

7 / 1 = 7
7 / 7 = 1

7 + 1 = 8

Salida: 8


Entrada: 15

15 / 1 = 15
15 / 3 = 5
15 / 5 = 3
15 / 15 = 1

15 + 5 + 3 + 1 = 24

Salida: 24


Entrada: 20

20 / 1 = 20
20 / 2 = 10
20 / 4 = 5
20 / 5 = 4
20 / 10 = 2
20 / 20 = 1

20 + 10 + 5 + 4 + 2 + 1 = 42

Salida: 42


Entrada: 1

1 / 1 = 1

Salida: 1


Entrada: 5

5 / 1 = 5
5 / 5 = 1

5 + 1 = 6

Salida: 6

Kevin Halley
fuente
66
@ H.PWiz Creo que quiere decir "los divisores de un número N"
benceno
Creo que te refieres a la suma de divisores, también conocida como la función sigma .
Stephen
Lo siento, quiero decir "La suma del múltiplo de N".
Kevin Halley
@ H.PWiz esta es la suma de esos, así que no sé
Stephen
@Stephen Eso me parece un cambio trivial
H.PWiz

Respuestas:

6

Código de máquina x86-64, 23 bytes

89 F9 89 FE EB 0D 89 F8 99 F7 F1 85 D2 99 0F 44 D1 01 D6 E2 F1 96 C3

Los bytes de código anteriores definen una función que acepta un solo entero, N, y como resultado devuelve la suma de sus múltiplos.

El parámetro único se pasa en el EDIregistro, de acuerdo con el System V AMD64 ABI (como se usa en los sistemas de estilo * nix). El resultado se devuelve en el EAXregistro, como con todas las convenciones de llamadas x86.

El algoritmo es muy sencillo, similar a muchos de los otros envíos en otros idiomas. Realizamos un bucle N veces, cada vez que calculamos el módulo y lo agregamos a nuestro total acumulado.

Mnemónicos de ensamblaje sin golf:

; unsigned SumOfMultiples(unsigned N  /* (EDI) */)
    mov     ecx, edi      ; make copy of input N, to be used as our loop counter
    mov     esi, edi      ; make copy of input N, to be used as our accumulator
    jmp     CheckEnd      ; jump directly to 'CheckEnd'
AddModulo:
    mov     eax, edi      ; make copy of input N, to be used as input to DIV instruction
    cdq                   ; short way of setting EDX to 0, based on EAX
    div     ecx           ; divide EDX:EAX by ECX, placing remainder in EDX
    test    edx, edx      ; test remainder, and set ZF if it is zero
    cdq                   ; again, set EDX to 0, without clobbering flags
    cmovz   edx, ecx      ; set EDX to ECX only if remainder was zero (EDX = ZF ? 0 : ECX)
    add     esi, edx      ; add EDX to accumulator
CheckEnd:
    loop    AddModulo     ; decrement loop counter (ECX), and keep looping if it != 0
    xchg    eax, esi      ; move result from accumulator (ESI) into EAX
    ret                   ; return, with result in EAX

Pruébalo en línea!

Parece que debería haber una forma de acortar esto, pero no puedo verlo. El módulo de cómputo en x86 requiere bastante código, ya que lo hace usando la instrucción DIV(o IDIV), y ambos usan registros de entrada fijos ( EDXy EAX), cuyos valores se bloquean (porque reciben los resultados, el resto y cociente, respectivamente).

Los únicos trucos reales aquí son los de golf bastante estándar:

  • He estructurado el código de una manera algo inusual para que pueda usar la LOOPinstrucción de estilo CISC , que es básicamente una combinación de DEC+ JNZcon el ECXregistro como el operando implícito.
  • Estoy usando XCHGal final en lugar de MOVporque el primero tiene una codificación especial de 1 byte cuando EAXes uno de los operandos.
  • Solía CDQponer a cero EDXen la preparación para la división, aunque para la división sin signo, normalmente lo pondría a cero usando a XOR. Sin embargo, XORsiempre tiene 2 bytes, mientras CDQque solo tiene 1 byte. Utilizo CDQnuevamente una segunda vez dentro del ciclo a cero EDX, antes de la CMOVZinstrucción. Esto funciona porque puedo garantizar que el cociente de la división (in EAX) siempre está sin signo, por lo que una extensión de inicio de sesión EDXse establecerá EDXigual a 0.
Cody Gray
fuente
3

Japt , 3 bytes

â)x

Pruébalo en línea!

Powelles
fuente
Alternativa:â x
Mr. Xcoder
@ Mr.Xcoder: no es realmente una alternativa; está haciendo exactamente lo mismo: la única diferencia es la elección del paréntesis.
Shaggy
O con la bandera -x, podría ser un byte
Encarnación de la ignorancia
3

Mathematica, 14 bytes

Tr@Divisors@#&   

o una respuesta de @Loki

Mathematica, 17 bytes

DivisorSum[#,#&]&
J42161217
fuente
@ Jennymathy Muy bien, gracias! Una forma equivalente y divertida de escribirlo también es: DivisorSum [#, # &] &
Rebel-Scum
@ Jennymathy Hmm, esto es aún mejor: ¡Total @ Divisors @ tiene solo 15 caracteres! Y funciona: por ejemplo, Total @ Divisors @ 15 da 24 como se esperaba. Mathematica FTW :)
Rebel-Scum
2
@Loki e Tr@Divisors@#&incluso mejor ;-)
J42161217
1
@Loki, el programa debe ser una función f=que tome una entrada f [x] por eso lo presento de esta manera. Bienvenido a PPCG
J42161217
3
Puedes usar Tr@*Divisorspara afeitarte un byte.
wchargin
3

C, C ++, C #, D, Java, 65 62 bytes

int d(int n){int s=0,i=1;for(;i<=n;++i)s+=n%i>0?0:i;return s;}

Esto funciona en todas las tesis 5 lenguajes de programación debido a similitudes.

Optimización C, C ++ y D: 62 60 bytes

En C ++ y D, los enteros se convierten implícitamente en booleanos (cero => falso, no cero => verdadero), por lo que no necesita tener el !=0

int d(int n){int s=0,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}

Optimización D: sistema de plantillas de golf, 55 bytes

T d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}

Código para probar :

C :

printf("%d %d %d %d %d", d(7), d(15), d(20), d(1), d(5));

C ++:

std::cout << d(7) << ' ' << d(15) << ' ' << d(20) << ' ' << d(1) << ' ' << d(5);

C# :

class FindSum
{
    int d(int n) { int s = 0, i = 1; for (; i <= n; ++i) s += n % i > 0 ? 0 : i; return s; }

    static void Main(string[] args)
    {
        var f = new FindSum();
        Console.WriteLine(string.Format("{0}, {1}, {2}, {3}, {4}", f.d(7), f.d(15), f.d(20), f.d(1), f.d(5)));
    }
}

D:

writeln(d(7));
writeln(d(15));
writeln(d(20));
writeln(d(1));
writeln(d(5));

Java:

public class FindSum {
    int d(int n){int s=0,i=1;for(;i<=n;++i)s+=n%i>0?0:i;return s;}

    public static void main(String[] args) {
        FindSum f = new FindSum();
        System.out.println(String.format("%d, %d, %d, %d, %d", f.d(7), f.d(15), f.d(20), f.d(1), f.d(5)));
    }
}
HatsuPointerKun
fuente
Algunas cosas: Primero, no creo que necesite paréntesis alrededor de n%i/ n%i!=0en ninguno de los idiomas. En segundo lugar, su primera solución debería poder tenerla en n%i>0lugar de n%i!=0. Tercero, la solución de D puede ser T d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}abusando del sistema de plantillas y los valores predeterminados.
Zacharý
3

Shnap , 44 43 bytes

-1 adiós gracias al Sr. Xcoder (jaja, me superaron en mi propio idioma)

 $n return:{s=0for d:range(n+1)if n%d<1s+=d}

Esta es una función ( $inicia una función en Shnap).

Pruébalo en línea!

Explicación:

$ n                        //Start function with parameter n
    return: {              //Technically, we are returning a scope-block, which evaluates to the last statement run
        s = 0              //Our result
        for d : range(n+1) //For each value in the iterator range(n+1)
            if n % d < 1  // If n is divisible by d
                s += d     // Add d to the sum
                           // Since (s += d) returns (s + d), and a scope-block returns the last run statement, this will be the last statement and equal to our result
    }

Sin competencia, 19 bytes

Después de muchas actualizaciones de idioma, ahora se puede reducir a unos miserables 19 bytes:

$n=>sum(factors(n))

Pruébalo en línea!

Fénix Socrático
fuente
1
==0es <1( 43 bytes )
Sr. Xcoder
@Señor. Xcoder, gracias ... Estaba superado por el golf ... En mi propio idioma ... Que ni siquiera es esotérico xD
Socratic Phoenix
2

Python, 44 bytes

lambda k:sum(i*(k%i<1)for i in range(1,1+k))
  • Gracias a Stephen, ahorre 1 byte eliminando espacios en blanco.
  • Gracias a Jonathan Frech, ahorre otro 1 byte cambiando si multiplicar.
tsh
fuente
2

J, 23 bytes

[:+/](([:=&0]|[)#])1+i.

Pruébalo en línea!

Para los fanáticos de J, hay una solución inteligente de 13 bytes : >:@#.~/.~&.q:pero como no fue mi invención, no la publico como mi respuesta oficial.

Mi propia solución simplemente filtra 1..n, encuentra divisores, luego los suma. El quid de la cuestión es el tenedor diádico.

](([:=&0]|[)#])

Tenga en cuenta que en este contexto ]es 1..n, y [es n en sí mismo. Por ]|[lo tanto, son los restos al dividir cada elemento de 1..n en n, y =&0le dice si son iguales a 0.

Jonás
fuente
2
Esto para 13 bytes debería ser equivalente:+1#.i.*0=i.|]
millas del
@miles, eso es realmente bueno. Esta parte es i.|]una gran mejora en mi enfoque. Sin embargo, no entiendo completamente esta parte: +1#.i.¿podría explicarlo?
Jonás
2
1#.es la conversión de base 1, que es equivalente a +/"1. Primero i.|]para obtener los restos, luego 0=para encontrar los iguales a 0 (los divisores), luego i.*poner a cero los no divisores en el rango, luego sumar usando 1#., luego sumar +ya que i.es un rango exclusivo.
millas
2

Javascript, 54 44 bytes

n=>[...Array(x=n)].reduce(y=>y+!(n%x)*x--,0)

Guardado 10 bytes gracias a Shaggy

Pruébalo en línea!

const f = n=>[...Array(x=n)].reduce(y=>y+!(n%x)*x--,0)

console.log(f(7))
console.log(f(15))
console.log(f(20))
console.log(f(1))
console.log(f(5))

Powelles
fuente
2

Brain-Flak , 96 bytes

((({})<>){<(([()]{})){<>(({})(<()>))<>{(({})){({}[()])<>}{}}{}<>([{}()]({})){((<{}{}>))}}{}>{}})

Pruébalo en línea!

Explicación:

Ahora anticuado por mejoras.

El corazón del algoritmo es este:

({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]({})) turns |N, M...| into |N mod M, M...|
{((<{}{}>))} if the top of stack is not zero, replace it and the second with zero

Que es una modificación de mod que nos dará Msi se trata de un factor de Ny 0de otra manera. El código completo está abajo.

((({})<>) place input, N on both stacks
{ Loop to find factors
 <
  (([()]{})) Decrement and Duplicate; get next factor to check
  { if not zero
   (<>({})<>) Copy N from other stack
   ({}(<>))<>{(({})){({}[()])<>}{}}{}<>([{}()]({})){((<{}{}>))} Code explained above
  }
  {} drop the zero
 >
 {} add the factor
}) push the sum
MegaTom
fuente
¿Tienes una explicación?
Wheat Wizard
@ FunkyComputerMan ¡Tengo uno ahora!
MegaTom
2

R , 31 26 bytes

function(N)(x=1:N)%*%!N%%x

Pruébalo en línea!

Devuelve una 1x1matriz.

Calcula !N%%xelementos dde mapas de 1:Npor:d->(1 if d divides N, 0 otherwise)

Entonces x%*%x!N%%xes el producto matricial 1:Ncuyo resultado es la suma de xdónde !N%%xestá 1. ¡Ordenado! Técnicamente un puerto de la respuesta Octave de Luis Mendo, pero solo lo vi después de pensar en esto.

Números R +, 14 bytes

numbers::Sigma

Pruébalo en línea!

Giuseppe
fuente
Para el primero, puede guardar 2 bytes conN=scan();
gstats
@gstats sí, pero debería obtener +4 bytes por meta discusión . Si tiene una opinión sólida, puede opinar sobre la respuesta de Jarko, pero como nadie ha sugerido una alternativa, eso se me ocurre.
Giuseppe
¿No debería ser el segundo numbers::Sigma(N) ? De esta manera, genera el código fuente de la función Sigma.
Rui Barradas - Restablecer Monic
@RuiBarradas una función es una presentación perfectamente buena. para probarlo, obviamente tienes que llamarlo como lo hago en la primera presentación.
Giuseppe
1

JavaScript, 31 bytes

f=(n,i=n)=>i&&!(n%i)*i+f(n,i-1)
tsh
fuente
1

VBA (Excel), 73 bytes

a=Cells(1,1)
x=1
While x<=a
If a Mod x = 0 Then b=b+x
x=x+1
Wend
MsgBox b
remodelar
fuente
Esta respuesta no es válida, ya que es una colección de fragmentos que no se pueden ejecutar como una sola unidad tal como están. Para que esto sea válido, deberá convertirlo a una subrutina o una función de ventana inmediata anónima de VBE.
Taylor Scott
No estoy muy familiarizado con lo que has dicho. ¿Me pueden ayudar un poco más?
Remoel
Para que esta publicación sea válida, tendría que convertirla en uno de los siguientes formatos: 1 - Subrutina, 2 - Función, 3 - Función de ventana inmediata VBE anónima (una sola línea que se puede ejecutar en la ventana Inmediato); Para su implementación, la implementación más simple de esto sería convertir a una subrutina envolviendo con Sub Y... End Subpara obtener la solución de 85 BytesSub y A=Cells(1,1) x=1 While x<=A If A Mod x=0 Then b=b+x x=x+1 Wend MsgBox b End Sub
Taylor Scott
Sin embargo, eso puede optimizarse en gran medida hasta la solución de 72 bytes Sub y While x<=[A1] x=x+1 If [A1]Mod x=0Then b=b+x Wend Debug.?b End Subque asume que se ejecuta en un módulo limpio (x = valor int predeterminado 0) y se envía a la ventana inmediata de VBE ( ?autoformatos para Print )
Taylor Scott
Más allá de esto, y reconociendo que su solución no toma de entrada a través de la llamada de subrutina, esto entonces se puede convertir en una función de ventana inmediata VBE de 50 bytes While x<=[A1]:x=x+1:b=IIf([A1]Mod x,b,b+x):Wend:?bque supone que x, bson el valor por defecto de 0 y salidas a la ventana inmediata VBE (de la ventana inmediata de VBE ?es equivalente a Debug.Print )
Taylor Scott
1

Pyth , 6 bytes

s*M{yP

Pruébalo aquí!

Pyth no tiene divisores incorporados, así que creo que esto es razonable.

Explicación

s * M {yP - Programa completo con entrada implícita.

     P - Los factores primos de la entrada.
    y - El conjunto de poder de sus factores primos.
   {- Deduplicar.
 * M - Mapa con multiplicación.
s - Suma.
          - Mostrar implícitamente el resultado.

Dado 20, por ejemplo, esto es lo que hace nuestro programa después de cada instrucción:

  • P: [2, 2, 5].

  • y: [[], [2], [2], [5], [2, 2], [2, 5], [2, 5], [2, 2, 5]].

  • {: [[], [2], [5], [2, 2], [2, 5], [2, 2, 5]].

  • *M: [1, 2, 5, 4, 10, 20].

  • s: 42.

Sr. Xcoder
fuente
1

Ohm v2 , 2 bytes

Pruébalo en línea!

Esto es bastante sencillo:

V - Divisores.
 Σ - Suma
Sr. Xcoder
fuente
Maldición, tú también me ganaste!
ThePlasmaRailgun
1

Casco , 5 bytes

ṁΠuṖp

Pruébalo en línea!

¿Cómo?

ṁΠuṖp: programa completo, entrada implícita.

     p - Factores primos.
    Ṗ - Powerset.
   u - Eliminar duplicados.
ṁΠ - Obtenga el producto de cada lista, suma y salida implícita.

¡Gracias a Zgarb por las sugerencias en el chat!

Sr. Xcoder
fuente
0

Bash + utilidades GNU, 36

bc<<<`seq -f"n=%g;a+=n*!$1%%n;" $1`a

Pruébalo en línea .


Pure Bash, 41

for((;++i<=$1;a+=$1%i?0:i))
{
:
}
echo $a

Pruébalo en línea .

Primero probé una elegante respuesta de expansión de bash, pero terminó siendo más larga que el simple ciclo anterior:

echo $[$(eval echo +\\\(n={1..$1},$1%n?0:n\\\))]
Trauma digital
fuente
0

Añadir ++ , 9 bytes

D,f,@,dFs

Pruébalo en línea!

Claramente llegué aquí demasiado tarde. Esto define una función que obtiene los factores y luego los suma.

caird coinheringaahing
fuente
0

QBIC , 17 bytes

[:|~b%a|\p=p+a}?p

Explicación

[:|      FOR a = 1; a <= b (read from cmd line); a++
~b%a|    IF b modulo a has a remainder THEN - empty block - 
\p=p+a   ELSE add divisor 'a' to running total 'p'
}        END IF, NEXT
?p       PRINT p
Steenbergh
fuente