Finden Sie die Summe der Teiler von N


20

Schreiben Sie ein Programm, das die Summe der Teiler einer vom Benutzer eingegebenen Zahl (1 ≤ N ≤ 100) im Bereich von 1 bis N auf dem Bildschirm anzeigt.

Dies ist OEIS A000203 .


Beispiele:

Eingabe : 7

7 / 1 = 7
7 / 7 = 1

7 + 1 = 8

Ausgabe: 8


Eingabe: 15

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

15 + 5 + 3 + 1 = 24

Ausgabe: 24


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

Ausgabe: 42


Eingabe: 1

1 / 1 = 1

Ausgang: 1


Eingabe: 5

5 / 1 = 5
5 / 5 = 1

5 + 1 = 6

Ausgabe: 6


6
@ H.PWiz Ich denke, er bedeutet "die Teiler einer Zahl N"
Benzol

Ich denke du meinst die Summe der Teiler, auch bekannt als die Sigma-Funktion ?
Stephen

Sorry, ich meine "Die Summe des Vielfachen von N".
Kevin Halley

@ H.PWiz das ist die Summe von denen, also weiß ich nicht
Stephen

@ Stephen Das scheint mir eine triviale Veränderung zu sein
H.PWiz

Antworten:



6

x86-64-Maschinencode, 23 Byte

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

Die obigen Codebytes definieren eine Funktion, die eine einzelne Ganzzahl N akzeptiert und als Ergebnis die Summe ihrer Vielfachen zurückgibt.

Der einzelne Parameter wird im EDIRegister übergeben, und zwar in Übereinstimmung mit dem System V AMD64 ABI (wie es auf * nix-artigen Systemen verwendet wird). Das Ergebnis wird EAXwie bei allen x86-Aufrufkonventionen im Register zurückgegeben.

Der Algorithmus ist sehr einfach, ähnlich wie bei vielen anderen Einsendungen in anderen Sprachen. Wir schleifen N-mal, jedes Mal, wenn wir das Modulo berechnen und das zu unserer laufenden Summe addieren.

Ungolfed Assembler-Mnemonik:

; 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

Probieren Sie es online!

Es scheint sicher, dass es einen Weg geben sollte, dies zu verkürzen, aber ich kann es nicht sehen. Das Berechnen von Modulo auf x86 erfordert eine Menge Code, da Sie dafür die Anweisung DIV(oder IDIV) verwenden und beide feste Eingaberegister ( EDXund EAX) verwenden, deren Werte überladen werden (weil sie die Ergebnisse, den Rest und die Informationen erhalten) Quotient).

Die einzigen echten Tricks sind die üblichen Golf-Tricks:

  • Ich habe den Code auf eine etwas ungewöhnliche Weise strukturiert, damit ich die CISC-artige LOOPAnweisung verwenden kann, die im Grunde genommen nur eine Kombination von DEC+ JNZmit dem ECXRegister als implizitem Operanden ist.
  • Ich benutze XCHGam Ende statt, MOVweil der erstere eine spezielle 1-Byte-Codierung hat, wenn EAXeiner der Operanden ist.
  • Ich verwende CDQzur EDXVorbereitung der Division Nullen, obwohl Sie für eine Division ohne Vorzeichen normalerweise nur Nullen verwenden würden, wenn Sie a verwenden XOR. Es sind jedoch XORimmer 2 Bytes, während CDQes nur 1 Byte sind. Ich benutze CDQwieder ein zweites Mal innerhalb der Schleife auf Null EDX, vor der CMOVZAnweisung. Dies funktioniert , weil ich kann garantiert werden , dass der Quotient der Division (in EAX) immer nicht unterzeichnet, so eine Zeichen-Erweiterung in EDXfestgelegt wird EDXgleich 0.




3

Mathematica, 14 Bytes

Tr@Divisors@#&   

oder eine Antwort von @Loki

Mathematica, 17 Bytes

DivisorSum[#,#&]&

@Jennymathy Sehr schön, danke! Eine äquivalente und lustige Art, es zu schreiben, ist auch: DivisorSum [#, # &] &
Rebel-Scum

@Jennymathy Hmm, das ist noch besser: Total @ Divisors @ ist nur 15 Zeichen lang! Und es funktioniert: zB Total @ Divisors @ 15 ergibt erwartungsgemäß 24. Mathematica FTW :)
Rebel-Scum

2
@Loki und Tr@Divisors@#&noch besser ;-)
J42161217

1
@Loki das Programm muss eine Funktion sein , f=die eine Eingabe f nimmt [x], deshalb habe ich es in diesem way.Welcome zu PPCG präsentieren
J42161217

3
Sie können verwenden Tr@*Divisors, um ein Byte zu rasieren.
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;}

Dies funktioniert in allen 5 Programmiersprachen aufgrund von Ähnlichkeiten.

C-, C ++ - und D-Optimierung: 62 bis 60 Byte

In C ++ und D werden Ganzzahlen implizit in Boolesche Werte konvertiert (Zero => false, Not Zero => true), sodass Sie das nicht benötigen !=0

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

D-Optimierung: Golf-Template-System, 55 Bytes

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

Code zum Testen :

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

Ein paar Dinge: Erstens glaube ich nicht, dass Sie Klammern um n%i/ n%i!=0in einer der Sprachen brauchen . Zweitens sollte Ihre erste Lösung in der Lage sein, n%i>0statt zu haben n%i!=0. Drittens kann die Lösung T d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}von D darin bestehen, das Vorlagensystem und die Standardwerte zu missbrauchen.
Zacharý

3

Shnap , 44 43 Bytes

-1 Tschüss, danke an Mr. Xcoder (lol ich war in meiner eigenen Sprache überfordert)

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

Dies ist eine Funktion ( $startet eine Funktion in Shnap).

Probieren Sie es online!

Erläuterung:

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

Nicht konkurrierend, 19 Bytes

Nach vielen Sprachupdates kann dies nun auf schlappe 19 Bytes reduziert werden:

$n=>sum(factors(n))

Probieren Sie es online!


1
==0ist <1( 43 Bytes )
Mr. Xcoder

@Herr. Xcoder danke ... Ich war überfordert ... In meiner eigenen Sprache ... Was nicht einmal esoterisch ist xD
Socratic Phoenix

2

Python, 44 Bytes

lambda k:sum(i*(k%i<1)for i in range(1,1+k))
  • Sparen Sie dank Stephen 1 Byte, indem Sie Leerzeichen entfernen.
  • Sparen Sie dank Jonathan Frech noch 1 Byte, indem Sie ändern, ob Sie multiplizieren möchten.

2

J, 23 Bytes

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

Probieren Sie es online!

Für J-Fans gibt es eine clevere 13-Byte-Lösung : >:@#.~/.~&.q:Da es aber nicht meine Erfindung war, werde ich sie nicht als meine offizielle Antwort veröffentlichen.

Meine eigene Lösung filtert einfach 1..n, findet Teiler und summiert sie dann. Der springende Punkt ist die dyadische Gabel

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

Beachten Sie, dass in diesem Kontext ]1..n und [n selbst ist. Daher ]|[sind die Reste, wenn Sie jedes Element von 1..n in n teilen und =&0Ihnen mitteilen, ob sie gleich 0 sind.


2
Dies für 13 Bytes sollte äquivalent sein:+1#.i.*0=i.|]
Meilen

@miles, das ist echt nett. Dieser Teil ist i.|]eine große Verbesserung meines Ansatzes. Ich verstehe diesen Teil allerdings nicht ganz: +1#.i.- Könnten Sie es erklären?
Jonah

2
1#.ist die Basis 1-Konvertierung, die äquivalent zu ist +/"1. Zuerst i.|]die Reste abrufen, dann 0=die gleich 0 (die Divisoren) finden, dann i.*die Nicht-Divisoren im Bereich auf Null setzen, dann mit 1#.summieren und +sich dann selbst addieren , da dies i.ein exklusiver Bereich ist.
Meilen




2

Javascript, 54 44 Bytes

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

Dank Shaggy 10 Bytes gespart

Probieren Sie es 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

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

Probieren Sie es online!

Erläuterung:

Jetzt überholt von Verbesserungen.

Das Herzstück des Algorithmus ist das Folgende:

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

Das ist eine Modifikation von Mod, die uns gibt, Mwenn es ein Faktor von Nund 0anders ist. Vollständiger Code ist unten.

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

Hast du eine Erklärung?
Weizen-Assistent

@FunkyComputerMan Ich habe jetzt eine!
MegaTom

2

R , 31 26 Bytes

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

Probieren Sie es online!

Gibt eine 1x1Matrix zurück.

Berechnet !N%%xKarten Elemente dvon 1:Ndurch:d->(1 if d divides N, 0 otherwise)

Dann x%*%x!N%%xist das Matrixprodukt, aus 1:Ndem sich die Summe ergibt, xwo !N%%xist 1. Ordentlich! Technisch gesehen eine Portierung von Luis Mendos Oktavantwort, aber das habe ich erst gesehen, nachdem ich darüber nachgedacht hatte.

R + Zahlen, 14 Bytes

numbers::Sigma

Probieren Sie es online!


Für die erste können Sie 2 Bytes speichern mitN=scan();
gstats

@gstats ja, aber dann sollte ich vier Bytes pro bekommen Meta Diskussion . Wenn Sie eine starke Meinung haben, können Sie die Antwort von Jarko abwägen, aber da niemand eine Alternative vorgeschlagen hat, fällt mir dies ein.
Giuseppe

Sollte nicht der zweite sein numbers::Sigma(N)? Auf diese Weise wird der Quellcode der Funktion ausgegeben Sigma.
Rui Barradas

@RuiBarradas a function is a perfectly good submission. to test it, you obviously have to call it as I do in the first submission.
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

This answer is invalid as it is a collection of snippets that cannot be run as a single unit as stands. To make this valid you will need to convert this to a subroutine or an anonymous VBE immediate window function.
Taylor Scott

I am not very familiar in what you had said. Can you help me a bit more?
remoel

To make this post valid you would have to convert it into one of the following formats, 1 - Subroutine, 2 - Function, 3 - Anonymous VBE immediate window function (a single line that can be executed in the Immediate window); For your implementation, the simplest implementation of this would be to convert to a subroutine by wrapping with Sub Y...End Sub to get the 85 Byte solution Sub 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

That however can be optimized quite heavily down to the 72 byte solution Sub y While x<=[A1] x=x+1 If [A1]Mod x=0Then b=b+x Wend Debug.?b End Sub which assumes that it is run in a clean module (x = default int value, 0) and outputs to the VBE immediate window (? autoformats to Print )
Taylor Scott

Beyond this, and recognizing that your solution does not take input via the subroutine call, this can then be converted to a VBE immediate window function for 50 Bytes While x<=[A1]:x=x+1:b=IIf([A1]Mod x,b,b+x):Wend:?b which assumes that x,b are the default value of 0 and outputs to the VBE immediate window (from the VBE immediate window ? is equivalent to Debug.Print )
Taylor Scott

1

Pyth, 6 bytes

s*M{yP

Try it here!

Pyth doesn't have a built-in for divisors, so I think this is reasonable.

Explanation

s*M{yP    - Full program with implicit input.

     P    - The prime factors of the input.
    y     - The powerset of its prime factors.
   {      - Deduplicate.
 *M       - Map with multiplication.
s         - Sum.
          - Implicitly display the result.

Given 20, for instance, this is what our program does after each instruction:

  • 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

Husk, 5 bytes

ṁΠuṖp

Try it online!

How?

ṁΠuṖp  - Full program, implicit input.

     p  - Prime factors.
    Ṗ   - Powerset.
   u    - Remove duplicates.
ṁΠ     - Get the product of each list, sum and implicitly output.

Thanks to Zgarb for the suggestions in chat!





0

Bash + GNU utilities, 36

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

Try it online.


Pure Bash, 41

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

Try it online.

I first tried a fancy bash expansion answer, but it ended up being longer than the simple loop above:

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


0

QBIC, 17 bytes

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

Explanation

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.