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


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.




3

Mathematica, 14 bytes

Tr@Divisors@#&   

o una respuesta de @Loki

Mathematica, 17 bytes

DivisorSum[#,#&]&

@ 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)));
    }
}

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!


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.

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.


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))


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

¿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!


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)



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

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.



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!





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\\\))]


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

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.