Temukan jumlah pembagi N

20

Tulis program yang menampilkan pada layar jumlah pembagi angka (1 ≤ N ≤ 100) yang dimasukkan oleh pengguna dalam kisaran 1 hingga N.

Ini adalah OEIS A000203 .


Contoh:

Input : 7

7 / 1 = 7
7 / 7 = 1

7 + 1 = 8

Output: 8


Input: 15

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

15 + 5 + 3 + 1 = 24

Output: 24


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

Output: 42


Input: 1

1 / 1 = 1

Output: 1


Input: 5

5 / 1 = 5
5 / 5 = 1

5 + 1 = 6

Output: 6

Kevin Halley
sumber
6
@ H.PWiz Saya pikir maksudnya "pembagi nomor N"
benzene
Saya pikir maksud Anda jumlah pembagi, alias, fungsi sigma ?
Stephen
Maaf, maksud saya "Jumlah dari kelipatan N".
Kevin Halley
@ H.Piz, ini adalah jumlah dari semua itu, jadi saya tidak tahu
Stephen
@Stephen Itu sepertinya perubahan sepele bagi saya
H.PWiz

Jawaban:

6

x86-64 Kode Mesin, 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

Byte kode di atas mendefinisikan fungsi yang menerima integer tunggal, N, dan mengembalikan jumlah kelipatannya sebagai hasilnya.

Parameter tunggal dilewatkan dalam EDIregister, konsisten dengan System V AMD64 ABI (seperti yang digunakan pada sistem * nix-style). Hasilnya dikembalikan dalam EAXregister, seperti semua konvensi pemanggilan x86.

Algoritma ini sangat mudah, mirip dengan banyak kiriman lainnya dalam bahasa lain. Kami mengulang N kali, setiap kali menghitung modulo dan menambahkannya ke total berjalan kami.

Mnemonik perakitan tidak dikumpulkan:

; 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

Cobalah online!

Sepertinya memang ada cara untuk membuatnya lebih pendek, tapi aku tidak bisa melihatnya. Komputasi modulo pada x86 membutuhkan sedikit kode, karena Anda melakukannya menggunakan instruksi DIV(atau IDIV), dan keduanya menggunakan register input tetap (EDX dan EAX), nilai-nilai yang menjadi musnah (karena mereka menerima hasil, sisanya dan bagi hasil, masing-masing).

Satu-satunya trik nyata di sini adalah yang golf standar:

  • Saya telah menyusun kode dengan cara yang agak tidak biasa sehingga saya dapat menggunakan LOOPinstruksi gaya CISC , yang pada dasarnya hanya kombinasi DEC+ JNZdengan ECXregister sebagai operan implisit.
  • Saya menggunakan XCHGdi akhir bukan MOVkarena yang pertama memiliki 1-byte encoding khusus ketika EAXadalah salah satu operan.
  • Saya gunakan CDQuntuk nol EDXdalam persiapan untuk divisi, meskipun untuk divisi tanpa tanda tangan Anda biasanya hanya akan nol menggunakan XOR. Namun, XORselalu 2 byte, sementara CDQhanya 1 byte. Saya menggunakan CDQlagi untuk kedua kalinya di dalam loop ke nol EDX, sebelum CMOVZinstruksi. Ini berfungsi karena saya dapat dijamin bahwa hasil bagi divisi (in EAX) selalu tidak ditandatangani, jadi perpanjangan tanda masuk EDXakan ditetapkan EDXsama dengan 0.
Cody Grey
sumber
3

Japt , 3 byte

â)x

Cobalah online!

powelles
sumber
Alternatif:â x
Tn. Xcoder
@ Mr.Xcoder: bukan benar-benar alternatif; itu melakukan hal yang sama persis - hanya perbedaan adalah pilihan kurung.
Shaggy
Atau dengan bendera -x, bisa jadi satu byte
Perwujudan Ketidaktahuan
3

Mathematica, 14 byte

Tr@Divisors@#&   

atau jawaban oleh @Loki

Mathematica, 17 byte

DivisorSum[#,#&]&
J42161217
sumber
@ Jennymathy Sangat bagus, terima kasih! Cara yang setara dan lucu untuk menulisnya juga: DivisorSum [#, # &] &
Rebel-Scum
@Jennymathy Hmm, ini bahkan lebih baik: Total @ Divisors @ panjangnya hanya 15 karakter! Dan itu berfungsi: mis. Total @ Divisors @ 15 memberi 24 seperti yang diharapkan. Mathematica FTW :)
Rebel-Scum
2
@Loki dan Tr@Divisors@#&bahkan lebih baik ;-)
J42161217
1
@Loki program harus merupakan fungsi f=yang mengambil input f [x] itu sebabnya saya menyajikannya dengan cara ini. Selamat datang di PPCG
J42161217
3
Anda dapat menggunakannya Tr@*Divisorsuntuk mengurangi byte.
wchargin
3

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

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

Ini bekerja di semua 5 bahasa pemrograman tesis karena kesamaan.

Optimasi C, C ++ dan D: 62 60 byte

Dalam C ++ dan D, integer dikonversi secara implisit menjadi boolean (Nol => salah, Bukan Nol => benar), jadi Anda tidak perlu memiliki !=0

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

D optimasi: sistem template golf, 55 byte

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

Kode untuk diuji :

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

Jawa:

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
sumber
Beberapa hal: Pertama, saya rasa Anda tidak perlu tanda kurung di sekitar n%i/ n%i!=0dalam salah satu bahasa. Kedua, solusi pertama Anda seharusnya bisa n%i>0bukan n%i!=0. Ketiga, solusi D dapat T d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}dengan menyalahgunakan sistem template dan nilai default.
Zacharý
3

Shnap , 44 43 byte

-1 sampai jumpa terima kasih kepada Tn. Xcoder (lol saya kalah dalam bahasa saya sendiri)

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

Ini adalah fungsi ( $memulai fungsi dalam Shnap).

Cobalah online!

Penjelasan:

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

Tidak bersaing, 19 byte

Setelah banyak pembaruan bahasa, ini sekarang dapat dikurangi menjadi 19 byte:

$n=>sum(factors(n))

Cobalah online!

Phoenix Sokrates
sumber
1
==0is <1( 43 bytes )
Mr. Xcoder
@Bapak. Terima kasih Xcoder ... Saya dikalahkan ... Dalam bahasa saya sendiri ... Yang bahkan bukan xD esoteris
Socratic Phoenix
2

Python, 44 byte

lambda k:sum(i*(k%i<1)for i in range(1,1+k))
  • Berkat Stephen, simpan 1 byte dengan menghapus spasi.
  • Terima kasih kepada Jonathan Frech, simpan 1 byte lagi dengan mengubah jika akan berlipat ganda.
tsh
sumber
2

J, 23 byte

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

Cobalah online!

Untuk penggemar J, ada solusi 13 byte yang pintar : >:@#.~/.~&.q:tapi karena itu bukan penemuan saya, saya tidak mempostingnya sebagai jawaban resmi saya.

Solusi saya sendiri cukup menyaring 1..n, menemukan pembagi, lalu menjumlahkannya. Inti dari itu adalah garpu diad

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

Perhatikan bahwa dalam konteks ini ]adalah 1..n, dan [adalah n itu sendiri. Karenanya ]|[adalah sisa ketika membagi setiap elemen dari 1..n menjadi n, dan =&0memberi tahu Anda jika mereka sama dengan 0.

Yunus
sumber
2
Ini untuk 13 byte harus setara:+1#.i.*0=i.|]
mil
@miles, itu sangat bagus. Bagian ini i.|]merupakan perbaikan besar pada pendekatan saya. Saya tidak sepenuhnya memahami bagian ini: +1#.i.- dapatkah Anda menjelaskannya?
Jonah
2
1#.adalah konversi basis 1, yang setara dengan +/"1. Pertama i.|]untuk mendapatkan sisanya, kemudian 0=untuk menemukan yang sama dengan 0 (pembagi), kemudian i.*untuk nol pembagi-pembagi dalam rentang, lalu jumlah menggunakan 1#., kemudian tambahkan +sendiri karena i.merupakan rentang eksklusif.
mil
2

Java (OpenJDK 8) , 53 51 byte

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

Cobalah online!

Nevay
sumber
1
@corsiKa Hanya bidang kelas. Dalam lingkup lokal mereka disatukan.
shooqie
2

Javascript, 54 44 byte

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

Disimpan 10 byte berkat Shaggy

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

powelles
sumber
2

Brain-Flak , 96 byte

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

Cobalah online!

Penjelasan:

Sekarang ketinggalan jaman dengan perbaikan.

Inti dari algoritma ini adalah:

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

Itu adalah modifikasi pada mod yang akan memberi kita Mjika itu adalah faktor Ndan 0sebaliknya. Kode lengkapnya ada di bawah ini.

((({})<>) 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
sumber
Apakah Anda punya penjelasan?
Wheat Wizard
@ FunkyComputerMan Saya punya satu sekarang!
MegaTom
2

R , 31 26 byte

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

Cobalah online!

Mengembalikan 1x1matriks.

Menghitung !N%%xpeta elemen ddari 1:Noleh:d->(1 if d divides N, 0 otherwise)

Maka x%*%x!N%%xadalah produk matriks 1:Nyang hasil dalam jumlah xmana !N%%xadalah 1. Rapi! Secara teknis pelabuhan Luis Mendo jawaban Oktaf tetapi saya hanya melihat itu setelah saya memikirkan hal ini.

Angka R +, 14 byte

numbers::Sigma

Cobalah online!

Giuseppe
sumber
Untuk yang pertama, Anda dapat menyimpan 2 byte denganN=scan();
gstats
@ gat ya, tapi kemudian saya harus mendapatkan +4 byte per diskusi meta . Jika Anda memiliki pendapat yang kuat, Anda dapat mempertimbangkan jawaban Jarko tetapi karena tidak ada yang menyarankan alternatif, itu ada dalam pikiran saya.
Giuseppe
Bukankah seharusnya yang kedua numbers::Sigma(N)? Seperti ini ia mengeluarkan kode sumber fungsi Sigma.
Rui Barradas
@RuiBarradas fungsi adalah pengiriman yang sangat baik. untuk mengujinya, Anda jelas harus memanggilnya seperti yang saya lakukan pada pengiriman pertama.
Giuseppe
1

JavaScript, 31 byte

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

VBA (Excel), 73 byte

a=Cells(1,1)
x=1
While x<=a
If a Mod x = 0 Then b=b+x
x=x+1
Wend
MsgBox b
remoel
sumber
Jawaban ini tidak valid karena merupakan kumpulan potongan yang tidak dapat dijalankan sebagai satu kesatuan sebagai tegakan. Untuk menjadikan ini valid, Anda perlu mengonversinya menjadi subrutin atau fungsi jendela langsung VBE anonim.
Taylor Scott
Saya tidak begitu akrab dengan apa yang Anda katakan. Bisakah Anda membantu saya sedikit lagi?
remoel
Untuk membuat postingan ini valid, Anda harus mengonversinya menjadi salah satu format berikut, 1 - Subroutine, 2 - Function, 3 - Anonymous VBE direct window function (satu baris yang dapat dieksekusi di jendela Immediate); Untuk implementasi Anda, implementasi paling sederhana dari ini adalah untuk mengkonversi ke subrutin dengan membungkus dengan Sub Y... End Subuntuk mendapatkan solusi 85 ByteSub 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
Namun itu dapat dioptimalkan cukup berat hingga solusi 72 byte Sub y While x<=[A1] x=x+1 If [A1]Mod x=0Then b=b+x Wend Debug.?b End Subyang mengasumsikan bahwa itu dijalankan dalam modul bersih (x = nilai int default, 0) dan output ke jendela langsung VBE ( ?autoformats ke Print )
Taylor Scott
Di luar ini, dan mengakui bahwa solusi Anda tidak mengambil input melalui panggilan subrutin, ini kemudian dapat dikonversi ke fungsi jendela langsung VBE untuk 50 Bytes While x<=[A1]:x=x+1:b=IIf([A1]Mod x,b,b+x):Wend:?byang mengasumsikan bahwa x, badalah nilai default 0 dan output ke jendela langsung VBE (dari jendela langsung VBE ?setara dengan Debug.Print )
Taylor Scott
1

Pyth , 6 byte

s*M{yP

Coba di sini!

Pyth tidak memiliki built-in untuk pembagi, jadi saya pikir ini masuk akal.

Penjelasan

s * M {yP - Program lengkap dengan input implisit.

     P - Faktor utama input.
    y - Kekuatan dari faktor utamanya.
   {- Deduplicate.
 * M - Peta dengan perkalian.
s - Jumlah.
          - Secara implisit menampilkan hasilnya.

Mengingat 20, misalnya, inilah yang dilakukan program kami setelah setiap instruksi:

  • 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.

Tuan Xcoder
sumber
1

Ohm v2 , 2 byte

Cobalah online!

Ini cukup jelas:

V - Pembagi.
 Σ - Jumlah
Tuan Xcoder
sumber
Sial, kau juga mengalahkanku!
ThePlasmaRailgun
1

Sekam , 5 byte

ṁΠuṖp

Cobalah online!

Bagaimana?

ṁΠuṖp - Program lengkap, input implisit.

     p - Faktor prima.
    Ṗ - Powerset.
   u - Hapus duplikat.
ṁΠ - Dapatkan produk dari setiap daftar, jumlah dan output secara implisit.

Terima kasih kepada Zgarb untuk sarannya dalam obrolan!

Tuan Xcoder
sumber
0

Utilitas Bash + GNU, 36

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

Cobalah online .


Pure Bash, 41

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

Cobalah online .

Saya pertama kali mencoba jawaban ekspansi bash mewah, tetapi akhirnya lebih panjang dari loop sederhana di atas:

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

Tambahkan ++ , 9 byte

D,f,@,dFs

Cobalah online!

Saya jelas terlambat sampai di sini. Ini mendefinisikan fungsi yang mendapatkan faktor, lalu menjumlahkannya.

caird coinheringaahing
sumber
0

QBIC , 17 byte

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

Penjelasan

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