ค้นหาผลรวมของตัวหารของ N


20

เขียนโปรแกรมที่แสดงบนหน้าจอผลรวมของตัวหารของตัวเลข (1 ≤ N entered 100) ที่ป้อนโดยผู้ใช้ในช่วง 1 ถึง N

นี่คือOEIS A000203


ตัวอย่าง:

อินพุต : 7

7 / 1 = 7
7 / 7 = 1

7 + 1 = 8

ผลลัพธ์: 8


อินพุต: 15

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

15 + 5 + 3 + 1 = 24

ผลลัพธ์: 24


อินพุต: 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

เอาท์พุต: 42


อินพุต: 1

1 / 1 = 1

ผลลัพธ์: 1


อินพุต: 5

5 / 1 = 5
5 / 5 = 1

5 + 1 = 6

ผลลัพธ์: 6


6
@ H.PWiz ฉันคิดว่าเขาหมายถึง "ตัวหารของจำนวน N"
เบนซิน

ฉันคิดว่าคุณหมายถึงผลรวมของตัวหาร, aka, ฟังก์ชันซิกมาหรือไม่
สตีเฟ่น

ขออภัยฉันหมายถึง "ผลรวมของผลคูณของ N"
Kevin Halley

@ H.PWiz นี่คือผลรวมของเหล่านั้นดังนั้นฉันจึงดู

@Stephen ที่ดูเหมือนว่ามีการเปลี่ยนแปลงเล็ก ๆ น้อย ๆ กับผม
H.PWiz

คำตอบ:



6

x86-64 รหัสเครื่อง 23 ไบต์

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

ไบต์ของรหัสข้างต้นกำหนดฟังก์ชั่นที่รับจำนวนเต็มเดียว, N, และส่งกลับผลรวมของทวีคูณของมันเป็นผล

พารามิเตอร์เดียวถูกส่งผ่านในEDIรีจิสเตอร์ซึ่งสอดคล้องกับ System V AMD64 ABI (ตามที่ใช้กับระบบสไตล์ * nix) ผลลัพธ์จะถูกส่งกลับในEAXรีจิสเตอร์เช่นเดียวกับอนุสัญญาการเรียก x86 ทั้งหมด

อัลกอริทึมเป็นสิ่งที่ตรงไปตรงมามากเช่นเดียวกับข้อเสนออื่น ๆ ในภาษาอื่น ๆ เราวนรอบ N ครั้งแต่ละครั้งที่คำนวณโมดูโลและเพิ่มเข้าไปในผลรวมการวิ่งของเรา

คำย่อของชุดประกอบ Ungolfed:

; 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

ลองออนไลน์!

ดูเหมือนว่าควรมีวิธีทำให้สั้นลง แต่ฉันมองไม่เห็น การคำนวณแบบโมดูโลบน x86 ใช้รหัสค่อนข้างน้อยเนื่องจากคุณใช้คำสั่งDIV(หรือIDIV) และทั้งคู่ใช้การลงทะเบียนอินพุตคงที่ ( EDXและEAX) ค่าที่ได้รับการอุดตัน (เพราะพวกเขาได้รับผลลัพธ์ส่วนที่เหลือและ ความฉลาดทางตามลำดับ)

เทคนิคจริงเท่านั้นที่นี่เป็นสนามกอล์ฟมาตรฐานสวย:

  • ฉันได้จัดทำโค้ดในลักษณะที่ผิดปกติเพื่อให้ฉันสามารถใช้LOOPคำสั่งแบบ CISC ซึ่งเป็นเพียงการรวมกันของDEC+ JNZกับการECXลงทะเบียนเป็นตัวถูกดำเนินการโดยปริยาย
  • ฉันใช้XCHGท้ายที่สุดแทนที่จะเป็นMOVเพราะอดีตมีการเข้ารหัส 1 ไบต์พิเศษเมื่อEAXเป็นหนึ่งในตัวถูกดำเนินการ
  • ผมใช้CDQเป็นศูนย์การในการเตรียมการสำหรับการแบ่งแม้สำหรับส่วนที่ไม่ได้ลงชื่อที่คุณจะปกติเพียงเป็นศูนย์โดยใช้EDX XORอย่างไรก็ตามXORมีขนาด 2 ไบต์เสมอในขณะที่CDQมีเพียง 1 ไบต์ ฉันใช้CDQอีกเป็นครั้งที่สองภายในของลูปเป็นศูนย์EDXก่อนCMOVZคำสั่ง สิ่งนี้ทำงานได้เพราะฉันสามารถรับประกันได้ว่าผลหารของหาร (ในEAX) นั้นไม่ได้ลงนามเสมอดังนั้นการเพิ่มส่วนขยายสัญญาณเข้าEDXจะEDXเท่ากับ 0


3

Japt , 3 ไบต์

â)x

ลองออนไลน์!


ทางเลือก:â x
นาย Xcoder

@ Mr.Xcoder: ไม่ใช่ทางเลือกจริงๆ มันกำลังทำสิ่งเดียวกัน - ความแตกต่างเพียงอย่างเดียวคือการเลือกวงเล็บ
Shaggy

หรือด้วยธง-xอาจเป็นหนึ่งไบต์
ศูนย์รวมแห่งความไม่รู้


3

Mathematica ขนาด 14 ไบต์

Tr@Divisors@#&   

หรือคำตอบโดย @Loki

Mathematica ขนาด 17 ไบต์

DivisorSum[#,#&]&

@ Jennymathy ดีมากขอบคุณ! วิธีที่เท่าเทียมและตลกในการเขียนคือ: DivisorSum [#, # &] &
Rebel-Scum

@ Jennymathy อืมดีกว่านี้อีก: Total @ Divisors @ มีความยาวเพียง 15 ตัวอักษร! และใช้งานได้: เช่น Total @ Divisors @ 15 ให้ 24 ตามที่คาดไว้ Mathematica FTW :)
Rebel-Scum

2
@Loki และTr@Divisors@#&ดียิ่งขึ้น ;-)
J42161217

1
@ โลกิโปรแกรมจะต้องเป็นฟังก์ชั่นf=ที่รับอินพุต f [x] นั่นเป็นเหตุผลที่ฉันนำเสนอด้วยวิธีนี้ยินดีต้อนรับสู่ PPCG
J42161217

3
คุณสามารถใช้Tr@*Divisorsเพื่อโกนเป็นไบต์
wchargin

3

C, C ++, C #, D, Java, 65 62 ไบต์

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

สิ่งนี้ใช้ได้กับภาษาการเขียนโปรแกรมทั้ง 5 ภาษาเพราะมีความคล้ายคลึงกัน

การเพิ่มประสิทธิภาพ C, C ++ และ D: 62 60 ไบต์

ใน C ++ และ D, จำนวนเต็มแปลงโดยปริยายเป็น booleans (Zero => false, ไม่ใช่ Zero => true) ดังนั้นคุณไม่จำเป็นต้องมี !=0

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

การปรับให้เหมาะสม D: ระบบเทมเพลต golfy, 55 ไบต์

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

รหัสที่จะทดสอบ :

ค :

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

ค# :

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

ชวา:

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

สองสามอย่าง: อย่างแรกฉันไม่คิดว่าคุณต้องใช้วงเล็บในn%i/ n%i!=0ในภาษาใด ๆ ประการที่สองการแก้ปัญหาครั้งแรกของคุณควรจะสามารถที่จะมีแทนn%i>0 n%i!=0ประการที่สามการแก้ปัญหาของ D สามารถทำได้T d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}โดยใช้ระบบแม่แบบและค่าเริ่มต้นที่ไม่เหมาะสม
Zacharý

3

Shnap , 44 43 ไบต์

-1 ลาก่อนขอบคุณ Mr. Xcoder (เพราะฉันเก่งภาษาของตัวเอง)

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

นี่คือฟังก์ชั่น ( $เริ่มฟังก์ชั่นใน Shnap)

ลองออนไลน์!

คำอธิบาย:

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

ไม่ใช่การแข่งขัน 19 ไบต์

หลังจากการอัปเดตหลายภาษาตอนนี้สามารถลดลงเหลือ 19 ไบต์

$n=>sum(factors(n))

ลองออนไลน์!


1
==0คือ<1( 43 bytes )
Mr. Xcoder

@นาย. ขอบคุณ Xcoder ... ฉันถูก outgolfed ... ในภาษาของฉันเอง ... ซึ่งไม่ใช่แม้แต่ความลับ xD
Socratic Phoenix

2

Python ขนาด 44 ไบต์

lambda k:sum(i*(k%i<1)for i in range(1,1+k))
  • ขอบคุณสตีเฟ่นบันทึก 1 ไบต์ด้วยการลบช่องว่าง
  • ขอบคุณ Jonathan Frech ให้บันทึกอีก 1 ไบต์ด้วยการเปลี่ยนถ้าคูณ

2

J, 23 ไบต์

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

ลองออนไลน์!

สำหรับแฟน ๆ เจมีวิธีการแก้ปัญหา 13 ไบต์ฉลาด : >:@#.~/.~&.q:แต่เนื่องจากมันไม่ได้เป็นสิ่งประดิษฐ์ของฉันฉันไม่ได้โพสต์เป็นคำตอบอย่างเป็นทางการของฉัน

โซลูชันของฉันเองเพียงแค่กรอง 1..n ค้นหาตัวหารแล้วหาผลรวม ปมของมันคือส้อม dyadic

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

โปรดทราบว่าในบริบทนี้]คือ 1..n และ[เป็น n เอง ดังนั้น]|[สิ่งที่เหลืออยู่เมื่อทำการหารแต่ละองค์ประกอบของ 1..n เป็น n และ=&0บอกคุณว่ามันเท่ากับ 0


2
สิ่งนี้สำหรับ 13 ไบต์ควรเท่ากัน:+1#.i.*0=i.|]
ไมล์

@miles ที่เป็นจริงที่ดี ส่วนนี้i.|]คือการปรับปรุงที่ดีในแนวทางของฉัน ฉันไม่เข้าใจส่วนนี้อย่างเต็มที่: +1#.i.- คุณช่วยอธิบายได้ไหม
โจนาห์

2
1#.เป็นฐาน 1 +/"1แปลงซึ่งเทียบเท่ากับ ก่อนอื่นi.|]ให้ได้ค่าเศษที่เหลือจากนั้น0=หาค่าเท่ากับ 0 (ตัวหาร) จากนั้นi.*ให้เหลือศูนย์ที่ไม่ใช่ตัวหารในช่วงจากนั้นจึงใช้ผลรวม1#.แล้วเพิ่ม+ตัวเองเนื่องจากi.เป็นช่วงพิเศษ
ไมล์




2

Javascript, 54 44 ไบต์

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

บันทึก 10 ไบต์ขอบคุณShaggy

ลองออนไลน์!

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 ไบต์

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

ลองออนไลน์!

คำอธิบาย:

ล้าสมัยแล้วจากการปรับปรุง

หัวใจของอัลกอริทึมคือ:

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

นั่นคือการดัดแปลงใน mod ที่จะให้เราMถ้ามันเป็นปัจจัยNและ0อื่น ๆ รหัสเต็มอยู่ด้านล่าง

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

คุณมีคำอธิบายไหม?
ข้าวสาลีตัวช่วยสร้าง

@FunkyComputerMan ฉันได้รับแล้ว!
MegaTom

2

R , 31 26 ไบต์

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

ลองออนไลน์!

ส่งคืน1x1เมทริกซ์

คำนวณ!N%%xแผนที่องค์ประกอบdของ1:Nโดย:d->(1 if d divides N, 0 otherwise)

จากนั้นx%*%x!N%%xเป็นผลิตภัณฑ์แมทริกซ์ของ1:Nซึ่งส่งผลให้ผลรวมของxที่เป็น!N%%x 1เรียบร้อย! ในทางเทคนิคแล้วพอร์ตของคำตอบอ็อกเทฟของ Luis Mendo แต่ฉันเห็นเพียงว่าหลังจากฉันคิดถึงสิ่งนี้

หมายเลขR + 14 ไบต์

numbers::Sigma

ลองออนไลน์!


สำหรับคนแรกคุณสามารถบันทึก 2 ไบต์ด้วยN=scan();
gstats

@gstats ใช่ แต่แล้วฉันควรจะได้รับ 4 ไบต์ต่อการอภิปรายเมตา หากคุณมีความคิดเห็นที่ดีคุณสามารถชั่งน้ำหนักในคำตอบของ Jarko ได้ แต่เนื่องจากไม่มีใครแนะนำทางเลือกอื่นนั่นคือสิ่งที่อยู่ในใจของฉัน
Giuseppe

ไม่ควรที่สองจะเป็นnumbers::Sigma(N)? Sigmaเช่นนี้มันจะออกผลลัพธ์ซอร์สโค้ดของฟังก์ชั่น
Rui Barradas

@RuiBarradas ฟังก์ชั่นคือการส่งที่ดีอย่างสมบูรณ์แบบ ในการทดสอบคุณต้องเรียกมันอย่างชัดเจนว่าเป็นฉันในการส่งครั้งแรก
Giuseppe




1

VBA (Excel) 73 ไบต์

a=Cells(1,1)
x=1
While x<=a
If a Mod x = 0 Then b=b+x
x=x+1
Wend
MsgBox b

คำตอบนี้ไม่ถูกต้องเนื่องจากเป็นคอลเล็คชั่นตัวอย่างที่ไม่สามารถเรียกใช้เป็นหน่วยเดียวได้ เพื่อให้ถูกต้องคุณจะต้องแปลงให้เป็นรูทีนย่อยหรือฟังก์ชั่นหน้าต่าง VBE ที่ไม่ระบุชื่อทันที
Taylor Scott

ฉันไม่คุ้นเคยกับสิ่งที่คุณพูด คุณช่วยฉันอีกเล็กน้อยได้ไหม
remoel

เพื่อให้โพสต์นี้ถูกต้องคุณจะต้องแปลงเป็นหนึ่งในรูปแบบดังต่อไปนี้ 1 - Subroutine, 2 - ฟังก์ชั่น, 3 - ฟังก์ชั่นหน้าต่างทันที VBE ไม่ระบุชื่อ (บรรทัดเดียวที่สามารถดำเนินการในหน้าต่างทันที); สำหรับการติดตั้งของคุณการใช้งานที่ง่ายที่สุดคือการแปลงเป็นรูทีนย่อยด้วยการห่อSub Y... End Subเพื่อรับโซลูชัน 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

ว่า แต่สามารถเพิ่มประสิทธิภาพค่อนข้างหนักลงไปที่การแก้ปัญหา 72 ไบต์Sub y While x<=[A1] x=x+1 If [A1]Mod x=0Then b=b+x Wend Debug.?b End Subซึ่งสันนิษฐานว่ามีการเรียกใช้ในโมดูลที่สะอาด (x = ค่า int ค่าเริ่มต้น0) และผลไปที่หน้าต่างทันที VBE ( ?autoformats ไปPrint )
เทย์เลอร์สกอตต์

นอกเหนือจากนี้และตระหนักว่าการแก้ปัญหาของคุณไม่ได้ใช้การป้อนข้อมูลผ่านทางโทร subroutine นี้จากนั้นจะสามารถแปลงเป็นฟังก์ชั่นหน้าต่าง VBE ทันทีสำหรับ 50 ไบต์While x<=[A1]:x=x+1:b=IIf([A1]Mod x,b,b+x):Wend:?bซึ่งสันนิษฐานว่าx, bเป็นค่าเริ่มต้นของ 0 และผลไปที่หน้าต่างทันที VBE (จาก หน้าต่าง VBE ?นั้นเทียบเท่ากับDebug.Print )
Taylor Scott

1

Pyth , 6 ไบต์

s*M{yP

ลองที่นี่!

Pyth ไม่ได้มีอุปกรณ์สำหรับตัวหารดังนั้นฉันคิดว่ามันสมเหตุสมผล

คำอธิบาย

s * M {yP - โปรแกรมเต็มรูปแบบพร้อมอินพุตโดยนัย

     P - ปัจจัยสำคัญของการป้อนข้อมูล
    y - ขุมพลังของปัจจัยสำคัญ
   {- ซ้ำซ้อน
 * M - แผนที่พร้อมการคูณ
s - ผลรวม
          - แสดงผลลัพธ์โดยนัย

ป.ร. ให้ไว้20เช่นนี้เป็นสิ่งที่โปรแกรมของเราไม่หลังจากที่แต่ละคำแนะนำ:

  • 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 ไบต์

ṁΠuṖp

ลองออนไลน์!

อย่างไร?

ṁΠuṖp - โปรแกรมเต็มอินพุตโดยปริยาย

     p - ปัจจัยสำคัญ
    Ṗ - Powerset
   u - ลบรายการที่ซ้ำกัน
ṁΠ - รับผลิตภัณฑ์ของแต่ละรายการผลรวมและผลลัพธ์โดยปริยาย

ขอบคุณ Zgarb สำหรับคำแนะนำในการแชท!





0

ยูทิลิตี Bash + GNU, 36

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

ลองมันออนไลน์


Pure Bash, 41

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

ลองมันออนไลน์

ครั้งแรกที่ฉันลองคำตอบการขยาย bash แฟนซี แต่มันก็นานกว่าการวนซ้ำแบบง่าย ๆ ข้างบน:

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


0

QBICขนาด 17 ไบต์

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

คำอธิบาย

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.