Encontre a soma dos divisores de N


20

Escreva um programa que exiba na tela a soma dos divisores de um número (1 ≤ N ≤ 100) inserido pelo usuário no intervalo de 1 a N.

Este é o OEIS A000203 .


Exemplos:

Entrada : 7

7 / 1 = 7
7 / 7 = 1

7 + 1 = 8

Saída: 8


Entrada: 15

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

15 + 5 + 3 + 1 = 24

Saída: 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

Saída: 42


Entrada: 1

1 / 1 = 1

Saída: 1


Entrada: 5

5 / 1 = 5
5 / 5 = 1

5 + 1 = 6

Saída: 6


6
@ H.PWiz Eu acho que ele significa "os divisores de um número N"
benzeno

Eu acho que você quer dizer soma de divisores, também conhecida como função sigma ?
Stephen

Desculpe, quero dizer "A soma do múltiplo de N".
Kevin Halley

@ H.PWiz esta é a soma desses, então eu não sei
Stephen

@Stephen Isso parece uma mudança trivial para mim
H.PWiz

Respostas:



6

Código da 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

Os bytes de código acima definem uma função que aceita um único número inteiro, N, e retorna a soma de seus múltiplos como resultado.

O único parâmetro é passado no EDIregistro, consistente com o System V AMD64 ABI (conforme usado nos sistemas * nix-style). O resultado é retornado no EAXregistro, como em todas as convenções de chamada x86.

O algoritmo é muito direto, semelhante a muitos dos outros envios em outros idiomas. Fazemos um loop N vezes, calculando o módulo cada vez e adicionando isso ao total da corrida.

Mnemônicos de montagem não destruídos:

; 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

Experimente online!

Parece que deve haver uma maneira de diminuir isso, mas não consigo ver. O módulo de computação no x86 exige bastante código, já que você faz isso usando a instrução DIV(ou IDIV) e os dois usam registradores de entrada fixos ( EDXe EAX), cujos valores são derrotados (porque recebem os resultados, o restante e quociente, respectivamente).

Os únicos truques reais aqui são os bastante comuns no golfe:

  • Estruturei o código de uma maneira um tanto incomum para poder usar a LOOPinstrução no estilo CISC , que é basicamente apenas uma combinação de DEC+ JNZcom o ECXregistrador como operando implícito.
  • Estou usando XCHGno final, em vez de MOVporque o primeiro tem uma codificação de 1 byte especial quando EAXé um dos operandos.
  • Eu uso CDQpara zerar EDXna preparação para a divisão, mesmo que para a divisão não assinada você normalmente a zere usando a XOR. No entanto, XORé sempre 2 bytes, enquanto CDQé de apenas 1 byte. Eu uso CDQnovamente uma segunda vez dentro do loop para zero EDX, antes da CMOVZinstrução. Isso funciona porque posso ter certeza de que o quociente da divisão (in EAX) sempre está sem sinal; portanto, uma extensão de sinal em EDXserá definida EDXcomo 0.




3

Mathematica, 14 bytes

Tr@Divisors@#&   

ou uma resposta de @Loki

Mathematica, 17 bytes

DivisorSum[#,#&]&

@Jennymathy Muito bom, obrigado! Uma maneira equivalente e engraçado de escrever é também: DivisorSum [#, # &] &
Rebel-Scum

@ Jennymathy Hmm, isso é ainda melhor: o total @ Divisores @ tem apenas 15 caracteres! E funciona: por exemplo, o Total @ Divisores @ 15 fornece 24 conforme o esperado. Mathematica FTW :)
Rebel-Scum

2
@Loki e Tr@Divisors@#&ainda melhor ;-)
J42161217

1
@Loki o programa deve ser uma função f=que leva uma entrada f [x] é por isso que eu apresentá-lo neste way.Welcome para PPCG
J42161217

3
Você pode usar Tr@*Divisorspara cortar um 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;}

Isso funciona em todas as 5 linguagens de programação por causa de semelhanças.

Otimização C, C ++ e D: 62 60 bytes

Em C ++ e D, números inteiros são convertidos implicitamente em booleanos (Zero => false, Not Zero => true), portanto, você não precisa ter o !=0

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

Otimização D: sistema de modelos de golfe, 55 bytes

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

Código a testar :

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

Algumas coisas: primeiro, acho que você não precisa de parênteses em torno do n%i/ n%i!=0em qualquer um dos idiomas. Segundo, sua primeira solução deve ser capaz de ter em n%i>0vez de n%i!=0. Terceiro, a solução de D pode ser T d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}abusar do sistema de modelos e dos valores padrão.
Zacharý 9/09/17

3

Shnap , 44 43 bytes

-1 bye graças ao Sr. Xcoder (lol eu fui derrotado no meu próprio idioma)

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

Esta é uma função ( $inicia uma função no Shnap).

Experimente online!

Explicação:

$ 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
    }

Não-competidor, 19 bytes

Após muitas atualizações de idioma, isso agora pode ser reduzido para apenas 19 bytes:

$n=>sum(factors(n))

Experimente online!


1
==0é <1( 43 bytes )
Sr. Xcoder 8/17

@Sr. Xcoder obrigado ... Eu estava outgolfed ... Na minha própria língua ... Que não é mesmo xD esotérica
socrático Phoenix

2

Python, 44 bytes

lambda k:sum(i*(k%i<1)for i in range(1,1+k))
  • Graças a Stephen, economize 1 byte removendo o espaço em branco.
  • Graças a Jonathan Frech, salve outro byte alterando se deseja multiplicar.

2

J, 23 bytes

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

Experimente online!

Para os fãs de J, existe uma solução inteligente de 13 bytes : >:@#.~/.~&.q:mas como essa não foi minha invenção, não a publicarei como minha resposta oficial.

Minha própria solução simplesmente filtra 1..n, localizando divisores e depois os soma. O ponto crucial é o garfo diádico

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

Observe que neste contexto ]é 1..n e [é n em si. Portanto, ]|[são os restantes ao dividir cada elemento de 1..n em n e =&0informa se são iguais a 0.


2
Isso para 13 bytes deve ser equivalente:+1#.i.*0=i.|]
miles

@ Miles, isso é muito bom. Esta parte é i.|]uma grande melhoria na minha abordagem. Não entendo completamente essa parte: +1#.i.- você poderia explicar?
Jonah

2
1#.é a conversão de base 1, que é equivalente a +/"1. Primeiro, i.|]para obter os restantes, depois 0=encontrar os iguais a 0 (os divisores), depois i.*zerar os não-divisores no intervalo, depois somar usando e 1#., em seguida, adicionar- +se, pois i.é um intervalo exclusivo.
miles




2

Javascript, 54 44 bytes

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

Economizou 10 bytes graças a Shaggy

Experimente online!

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

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

Experimente online!

Explicação:

Agora desatualizado por melhorias.

O coração do algoritmo é este:

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

Essa é uma modificação no mod que nos dará Mse é um fator de Nou 0não. O código completo está abaixo.

((({})<>) 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

Você tem uma explicação?
Wheat Wizard

@FunkyComputerMan Eu tenho um agora!
MegaTom 21/09

2

R , 31 26 bytes

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

Experimente online!

Retorna uma 1x1matriz.

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

Então x%*%x!N%%xé o produto da matriz 1:Nque resulta na soma de xonde !N%%xestá 1. Arrumado! Tecnicamente, um porto da resposta Octave de Luis Mendo mas só vi isso depois de pensar nisso.

Números R +, 14 bytes

numbers::Sigma

Experimente online!


Para o primeiro, você pode salvar 2 bytes comN=scan();
gstats 8/17

@ gstats sim, mas então eu deveria receber +4 bytes por meta-discussão . Se você tem uma opinião forte, pode avaliar a resposta de Jarko, mas como ninguém sugeriu uma alternativa, isso está na minha mente.
Giuseppe

Não deveria ser o segundo numbers::Sigma(N)? Assim, ele gera o código fonte da função Sigma.
Rui Barradas

A função @RuiBarradas é uma apresentação perfeitamente boa. para testá-lo, você obviamente precisa chamá-lo como eu faço na primeira submissão.
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 resposta é inválida, pois é uma coleção de trechos que não podem ser executados como uma única unidade como está. Para tornar isso válido, você precisará convertê-lo em uma sub-rotina ou em uma função de janela imediata anônima do VBE.
Taylor Scott

Não estou muito familiarizado com o que você disse. Você pode me ajudar um pouco mais?
remoel 18/09/17

Para validar esta publicação, você teria que convertê-la em um dos seguintes formatos: 1 - Sub-rotina, 2 - Função, 3 - Função de janela imediata VBE anônima (uma única linha que pode ser executada na janela Imediata); Para sua implementação, a implementação mais simples disso seria converter para uma sub-rotina envolvendo Sub Y... End Subpara obter a solução 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 #

Isso, porém, pode ser optimizada bastante fortemente para baixo para a solução de 72 bytes Sub y While x<=[A1] x=x+1 If [A1]Mod x=0Then b=b+x Wend Debug.?b End Sub, que assume que é executado num módulo limpo (x = int valor padrão, 0) e saídas para a janela imediato do VBE ( ?AutoFormats a Print )
Taylor Scott

Além disso, e reconhecendo que sua solução não recebe entrada por meio da chamada de sub-rotina, isso pode ser convertido em uma função de janela imediata do VBE para 50 bytes, While x<=[A1]:x=x+1:b=IIf([A1]Mod x,b,b+x):Wend:?bque pressupõe que x, bsão o valor padrão de 0 e saem para a janela imediata do VBE (de janela imediato do VBE ?é equivalente a Debug.Print )
Taylor Scott

1

Pitão , 6 bytes

s*M{yP

Experimente aqui!

Pyth não tem um built-in para divisores, então acho que isso é razoável.

Explicação

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

     P - Os fatores primos da entrada.
    y - O conjunto de seus principais fatores.
   {- Desduplicar.
 * M - Mapa com multiplicação.
s - soma.
          - Exiba implicitamente o resultado.

Dado 20, por exemplo, é isso que nosso programa faz após cada instrução:

  • 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

Casca , 5 bytes

ṁΠuṖp

Experimente online!

Quão?

--uṖp - Programa completo, entrada implícita.

     p - fatores primos.
    P - Powerset.
   u - Remova duplicatas.
Get - Obtenha o produto de cada lista, soma e saída implícita.

Obrigado ao Zgarb pelas sugestões no chat!





0

Utilitários Bash + GNU, 36

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

Experimente online .


Pure Bash, 41

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

Experimente online .

Tentei pela primeira vez uma resposta sofisticada de expansão do bash, mas acabou sendo mais longa que o loop simples acima:

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


0

QBIC , 17 bytes

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

Explicação

[:|      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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.