Tìm tổng các ước của N


20

Viết chương trình hiển thị trên màn hình tổng các ước của một số (1 ≤ N 100) được người dùng nhập trong phạm vi từ 1 đến N.

Đây là OEIS A000203 .


Ví dụ:

Đầu vào : 7

7 / 1 = 7
7 / 7 = 1

7 + 1 = 8

Đầu ra: 8


Đầu vào: 15

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

15 + 5 + 3 + 1 = 24

Đầu ra: 24


Đầu vào: 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

Đầu ra: 42


Đầu vào: 1

1 / 1 = 1

Đầu ra: 1


Đầu vào: 5

5 / 1 = 5
5 / 5 = 1

5 + 1 = 6

Đầu ra: 6


6
@ H.PWiz Tôi nghĩ rằng anh ấy có nghĩa là "ước số của một số N"
benzen

Tôi nghĩ bạn có nghĩa là tổng của ước, hay còn gọi là hàm sigma ?
Stephen

Xin lỗi, ý tôi là "Tổng của bội số N".
Kevin Halley

@ H.PWiz đây là tổng của những người đó, vì vậy tôi không biết
Stephen

@Stephen Điều đó có vẻ như là một thay đổi nhỏ đối với tôi
H.PWiz

Câu trả lời:



6

Mã máy x86-64, 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

Các byte mã trên xác định một hàm chấp nhận một số nguyên duy nhất, N và trả về tổng số bội của nó là kết quả.

Tham số đơn được truyền trong thanh EDIghi, phù hợp với System V AMD64 ABI (như được sử dụng trên các hệ thống kiểu * nix). Kết quả được trả về trong EAXsổ đăng ký, như với tất cả các quy ước gọi x86.

Thuật toán này rất đơn giản, tương tự như nhiều bài nộp khác trong các ngôn ngữ khác. Chúng tôi lặp N lần, mỗi lần tính toán modulo và thêm nó vào tổng số đang chạy của chúng tôi.

Ma thuật lắp ráp bất khả xâm phạm:

; 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

Hãy thử trực tuyến!

Có vẻ như có một cách để làm cho nó ngắn hơn, nhưng tôi không thể nhìn thấy nó. Việc tính toán modulo trên x86 mất khá nhiều mã, vì bạn thực hiện bằng cách sử dụng lệnh DIV(hoặc IDIV) và cả hai đều sử dụng các thanh ghi đầu vào cố định ( EDXEAX), các giá trị bị ghi đè (vì chúng nhận được kết quả, phần còn lại và thương số, tương ứng).

Thủ thuật thực sự duy nhất ở đây là những cú đánh golf khá chuẩn:

  • Tôi đã cấu trúc mã theo một cách hơi khác thường để tôi có thể sử dụng LOOPhướng dẫn kiểu CISC , về cơ bản chỉ là sự kết hợp của DEC+ JNZvới thanh ECXghi làm toán hạng ngầm.
  • Tôi đang sử dụng XCHGở cuối thay MOVvì vì trước đây có mã hóa 1 byte đặc biệt khi EAXlà một trong các toán hạng.
  • Tôi sử dụng CDQđể zero out EDXđể chuẩn bị cho việc phân chia, mặc dù đối với phép chia không dấu, bạn thường chỉ bằng 0 khi sử dụng a XOR. Tuy nhiên, XORluôn là 2 byte, trong khi CDQchỉ là 1 byte. Tôi sử dụng CDQlại lần thứ hai trong vòng lặp về 0 EDX, trước khi CMOVZhướng dẫn. Điều này hoạt động bởi vì tôi có thể được đảm bảo rằng thương số của phép chia (in EAX) luôn không được ký, vì vậy một phần mở rộng đăng nhập vào EDXsẽ được đặt EDXbằng 0.




3

Toán học, 14 byte

Tr@Divisors@#&   

hoặc câu trả lời của @Loki

Toán học, 17 byte

DivisorSum[#,#&]&

@Jennymathy Rất hay, cảm ơn! Một cách tương đương và hài hước để viết nó cũng là: DivisorSum [#, # &] &
Rebel-Scum

@Jennymathy Hmm, điều này thậm chí còn tốt hơn: Total @ Divisors @ chỉ dài 15 ký tự! Và nó hoạt động: ví dụ: Total @ Divisors @ 15 cho 24 như mong đợi. Mathicala FTW :)
Rebel-Scum

2
@Loki và Tr@Divisors@#&thậm chí tốt hơn ;-)
J42161217

1
@Loki chương trình phải là một hàm f=lấy đầu vào f [x] đó là lý do tại sao tôi trình bày nó theo cách này. Chào mừng bạn đến với PPCG
J42161217

3
Bạn có thể sử dụng Tr@*Divisorsđể cạo một byte.
wchargein

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

Điều này hoạt động trong tất cả 5 ngôn ngữ lập trình vì sự tương đồng.

Tối ưu hóa C, C ++ và D: 62 60 byte

Trong C ++ và D, số nguyên chuyển đổi hoàn toàn thành booleans (Zero => false, Not Zero => true), vì vậy bạn không cần phải có !=0

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

Tối ưu hóa D: hệ thống mẫu golf, 55 byte

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

Mã để kiểm tra :

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

Đ:

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

Một vài điều: Đầu tiên, tôi không nghĩ bạn cần dấu ngoặc đơn xung quanh n%i/ n%i!=0trong bất kỳ ngôn ngữ nào. Thứ hai, giải pháp đầu tiên của bạn sẽ có thể có n%i>0thay vì n%i!=0. Thứ ba, giải pháp của D có thể T d(T)(T n){T s,i=1;for(;i<=n;++i)s+=n%i?0:i;return s;}bằng cách lạm dụng hệ thống mẫu và các giá trị mặc định.
Zacharý

3

Shnap , 44 43 byte

-1 tạm biệt nhờ có ông Xcoder (lol tôi đã vượt qua chính ngôn ngữ của mình)

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

Đây là một chức năng ($ bắt đầu một chức năng trong Shnap).

Hãy thử trực tuyến!

Giải trình:

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

Không lọc, 19 byte

Sau nhiều lần cập nhật ngôn ngữ, giờ đây có thể giảm xuống còn 19 byte:

$n=>sum(factors(n))

Hãy thử trực tuyến!


1
==0<1( 43 byte )
Ông Xcoder

@Ông. Xcoder cảm ơn ... Tôi đã hết hồn ... Bằng ngôn ngữ của riêng tôi ... Điều đó thậm chí không bí truyền xD
Socratic Phoenix

2

Python, 44 byte

lambda k:sum(i*(k%i<1)for i in range(1,1+k))
  • Nhờ Stephen, tiết kiệm 1 byte bằng cách xóa khoảng trắng.
  • Nhờ Jonathan Frech, lưu thêm 1 byte bằng cách thay đổi nếu nhân lên.

2

J, 23 byte

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

Hãy thử trực tuyến!

Đối với người hâm mộ J, có một giải pháp 13 byte thông minh : >:@#.~/.~&.q:nhưng vì đó không phải là phát minh của tôi nên tôi không đăng nó dưới dạng câu trả lời chính thức.

Giải pháp của riêng tôi chỉ đơn giản là lọc 1..n, tìm ước số, sau đó tính tổng chúng. Mấu chốt của nó là ngã ba dyadic

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

Lưu ý rằng trong bối cảnh ]này là 1..n, và [là n chính nó. Do đó ]|[, phần còn lại khi chia từng phần tử của 1..n thành n và =&0cho bạn biết nếu chúng bằng 0.


2
Điều này cho 13 byte nên tương đương:+1#.i.*0=i.|]
dặm

@miles, thật là tốt Phần này i.|]là một cải tiến lớn trong cách tiếp cận của tôi. Tôi hoàn toàn không hiểu phần này: +1#.i.- bạn có thể giải thích nó không?
Giô-na

2
1#.là chuyển đổi cơ sở 1, tương đương với +/"1. Đầu tiên i.|]để lấy phần dư, sau đó 0=tìm những phần tử bằng 0 (ước số), sau đó i.*loại bỏ các phần tử không chia trong phạm vi, sau đó tính tổng 1#., sau đó thêm +chính nó i.là một phạm vi độc quyền.
dặm




2

Javascript, 54 44 byte

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

Đã lưu 10 byte nhờ Shaggy

Hãy thử trực tuyến!

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 byte

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

Hãy thử trực tuyến!

Giải trình:

Bây giờ lỗi thời bởi những cải tiến.

Trọng tâm của thuật toán này là:

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

Đó là một sửa đổi trên mod sẽ cung cấp cho chúng tôi Mnếu đó là một yếu tố của N0nếu không. Mã đầy đủ dưới đây.

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

Bạn có một lời giải thích?
Thuật sĩ lúa mì

@FunkyComputerMan Tôi có ngay bây giờ!
MegaTom

2

R , 31 26 byte

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

Hãy thử trực tuyến!

Trả về một 1x1ma trận.

Tính toán !N%%xcác yếu tố bản đồ dcủa 1:N:d->(1 if d divides N, 0 otherwise)

Sau đó x%*%x!N%%xlà sản phẩm ma trận 1:Nmà kết quả trong tổng số xnơi !N%%x1. Khéo léo! Về mặt kỹ thuật là một câu trả lời Octave của Luis Mendo nhưng tôi chỉ thấy điều đó sau khi tôi nghĩ về điều này.

Số R +, 14 byte

numbers::Sigma

Hãy thử trực tuyến!


Đối với cái đầu tiên, bạn có thể lưu 2 byte vớiN=scan();
gstats

@gstats có, nhưng sau đó tôi sẽ nhận được 4 byte cho mỗi cuộc thảo luận meta . Nếu bạn có một quan điểm mạnh mẽ, bạn có thể cân nhắc câu trả lời của Jarko nhưng vì không ai đề xuất một giải pháp thay thế, điều đó tồn tại trong tâm trí tôi.
Giuseppe

Không nên là thứ hai numbers::Sigma(N)? Như thế này, nó xuất ra mã nguồn của hàm Sigma.
Rui Barradas

@RuiBarradas một chức năng là một đệ trình hoàn toàn tốt. để kiểm tra nó, rõ ràng bạn phải gọi nó như tôi làm trong lần gửi đầu tiên.
Giuseppe

1

JavaScript, 31 byte

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



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

Câu trả lời này không hợp lệ vì nó là một tập hợp các đoạn không thể chạy dưới dạng một đơn vị dưới dạng đứng. Để làm cho điều này hợp lệ, bạn sẽ cần phải chuyển đổi nó thành một chương trình con hoặc một hàm cửa sổ ngay lập tức VBE ẩn danh.
Taylor Scott

Tôi không quen thuộc lắm trong những gì bạn đã nói. Bạn có thể giúp tôi thêm một chút?
làm lại

Để làm cho bài đăng này hợp lệ, bạn sẽ phải chuyển đổi nó thành một trong các định dạng sau, 1 - Chương trình con, 2 - Hàm, 3 - Hàm cửa sổ tức thời VBE ẩn danh (một dòng duy nhất có thể được thực thi trong cửa sổ Ngay lập tức); Đối với việc triển khai của bạn, cách thực hiện đơn giản nhất này sẽ là chuyển đổi sang chương trình con bằng cách gói với Sub Y... End Subđể có được giải pháp 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

Tuy nhiên, điều đó có thể được tối ưu hóa khá nhiều cho giải pháp 72 byte Sub y While x<=[A1] x=x+1 If [A1]Mod x=0Then b=b+x Wend Debug.?b End Sub, giả sử rằng nó được chạy trong một mô-đun sạch (x = giá trị int mặc định 0) và xuất ra cửa sổ ngay lập tức VBE ( ?tự động định dạng Print )
Taylor Scott

Ngoài ra, và nhận ra rằng giải pháp của bạn không nhận đầu vào thông qua lệnh gọi chương trình con, điều này sau đó có thể được chuyển đổi thành hàm cửa sổ tức thời VBE cho 50 Byte While x<=[A1]:x=x+1:b=IIf([A1]Mod x,b,b+x):Wend:?b, giả sử rằng x, blà giá trị mặc định là 0 và xuất ra cửa sổ ngay lập tức VBE (từ cửa sổ ngay lập tức VBE ?tương đương với Debug.Print )
Taylor Scott

1

Bình thường , 6 byte

s*M{yP

Hãy thử nó ở đây!

Pyth không tích hợp sẵn cho các ước số, vì vậy tôi nghĩ điều này là hợp lý.

Giải trình

s * M {yP - Chương trình đầy đủ với đầu vào ẩn.

     P - Các yếu tố chính của đầu vào.
    y - Quyền hạn của các yếu tố chính của nó.
   {- Khử trùng lặp.
 * M - Bản đồ với phép nhân.
s - Tổng.
          - Hiển thị rõ ràng kết quả.

Với 20Ví dụ, đây là những gì chương trình của chúng tôi không sau mỗi lệnh:

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

ṁΠuṖp

Hãy thử trực tuyến!

Làm sao?

ṁΠuṖp - Chương trình đầy đủ, đầu vào ẩn.

     p - Các yếu tố chính.
    Ṗ - Quyền hạn.
   u - Loại bỏ trùng lặp.
- Nhận sản phẩm của từng danh sách, tổng hợp và đầu ra ngầm.

Cảm ơn Zgarb về những gợi ý trong trò chuyện!







0

QBIC , 17 byte

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

Giải trình

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.