Código de máquina x86-64, 26 bytes
31 C9 8D 71 01 89 F8 FF C1 99 F7 F9 85 D2 75 03 0F AF F1 39 F9 7C EE 89 F0 C3
El código anterior define una función que toma un solo parámetro (el valor de entrada, un entero positivo) en EDI
(siguiendo la convención de llamada AMD64 del Sistema V utilizado en Gnu / Unix), y devuelve un único resultado (el producto de los divisores) en EAX
.
Internamente, calcula el producto de los divisores utilizando un algoritmo iterativo (extremadamente ineficiente), similar al envío C de pizzapants184 . Básicamente, utiliza un contador para recorrer todos los valores entre 1 y el valor de entrada, verificando si el valor del contador actual es un divisor de la entrada. Si es así, multiplica eso en el producto total acumulado.
Mnemónicos de lenguaje ensamblador sin golf:
; Parameter is passed in EDI (a positive integer)
ComputeProductOfDivisors:
xor ecx, ecx ; ECX <= 0 (our counter)
lea esi, [rcx + 1] ; ESI <= 1 (our running total)
.CheckCounter:
mov eax, edi ; put input value (parameter) in EAX
inc ecx ; increment counter
cdq ; sign-extend EAX to EDX:EAX
idiv ecx ; divide EDX:EAX by ECX
test edx, edx ; check the remainder to see if divided evenly
jnz .SkipThisOne ; if remainder!=0, skip the next instruction
imul esi, ecx ; if remainder==0, multiply running total by counter
.SkipThisOne:
cmp ecx, edi ; are we done yet? compare counter to input value
jl .CheckCounter ; if counter hasn't yet reached input value, keep looping
mov eax, esi ; put our running total in EAX so it gets returned
ret
El hecho de que la IDIV
instrucción utilice operandos codificados para el dividendo obstaculiza un poco mi estilo, pero creo que esto es bastante bueno para un lenguaje que no tiene incorporados sino aritmética básica y ramas condicionales.