Tính tổng của n số nguyên tố đầu tiên


15

Tôi ngạc nhiên rằng thử thách này chưa có ở đây, vì nó quá rõ ràng. (Hoặc tôi ngạc nhiên tôi không thể tìm thấy nó và bất kỳ ai cũng sẽ đánh dấu nó là một bản sao.)

Bài tập

Cho một số nguyên không âm n, tính tổng của n số nguyên tố đầu tiên và xuất nó.

Ví dụ 1

Với n=5 , năm số nguyên tố đầu tiên là:

  • 2
  • 3
  • 5
  • 7
  • 11

Tổng của các số này là 2+3+5+7+11=28 , vì vậy chương trình phải xuất 28 .

Ví dụ # 2

Với n=0 , số nguyên tố "số 0 đầu tiên" là không có. Và tổng của không có số là - tất nhiên - 0 .

Quy tắc

  • Bạn có thể sử dụng các phần dựng sẵn, ví dụ, để kiểm tra xem một số có phải là số nguyên tố hay không.
  • Đây là , vì vậy số byte thấp nhất trong mỗi ngôn ngữ sẽ thắng!



2
OEIS - A7504 (sang một bên: LOL ở phần này trong phần công thức, "a (n) = A033286 (n) - A152535 (n).")
Jonathan Allan

@Jonathan ALLan: Liên quan, nhưng không tương đương. Tôi nghĩ đó là một sự khác biệt quan trọng nếu bạn kiểm tra các số nguyên tố trong phạm vi hoặc một số số nguyên tố. Điểm chung của cả hai nhiệm vụ là a) kiểm tra xem một số có phải là số nguyên tố không và b) tổng hợp các số - điều này phổ biến đối với nhiều tác vụ chơi gôn ở đây.
xanoetux

Câu trả lời:


15

Thường trình mã máy 6502 , 75 byte

A0 01 84 FD 88 84 FE C4 02 F0 32 E6 FD A0 00 A5 FD C9 04 90 1F 85 64 B1 FB 85
65 A9 00 A2 08 06 64 2A C5 65 90 02 E5 65 CA D0 F4 C9 00 F0 DC C8 C4 FE D0 DB
A5 FD A4 FE 91 FB C8 D0 C8 A9 00 18 A8 C4 FE F0 05 71 FB C8 D0 F7 60

Yêu cầu một con trỏ tới một số lưu trữ tạm thời trong $fb/ $fcvà số lượng các số nguyên tố để tổng hợp $2. Trả về tổng bằng A(thanh ghi accu).

Chưa bao giờ thực hiện một số kiểm tra chính trong mã máy 6502, vì vậy cuối cùng nó cũng xuất hiện;)

Lưu ý rằng điều này bắt đầu đưa ra kết quả sai cho đầu vào> = 14. Điều này là do tràn, mã hoạt động với phạm vi số "tự nhiên" của nền tảng 8 bit 0 - 255dành cho không dấu .

Bình luận tháo gỡ

; function to sum the first n primes
;
; input:
;   $fb/$fc: pointer to a buffer for temporary storage of primes
;   $2:      number of primes to sum (n)
; output:
;   A:       sum of the first n primes
; clobbers:
;   $fd:     current number under primality test
;   $fe:     number of primes currently found
;   $64:     temporary numerator for modulo check
;   $65:     temporary divisor for modulo check
;   X, Y
 .primesum:
A0 01       LDY #$01            ; init variable for ...
84 FD       STY $FD             ; next prime number to test
88          DEY                 ; init number of found primes
 .mainloop:
84 FE       STY $FE             ; store current number of found primes
C4 02       CPY $02             ; compare with requested number
F0 32       BEQ .sum            ; enough primes -> calculate their sum
 .mainnext:
E6 FD       INC $FD             ; check next prime number
A0 00       LDY #$00            ; start check against first prime number
 .primecheckloop:
A5 FD       LDA $FD             ; load current number to check
C9 04       CMP #$04            ; smaller than 4?
90 1F       BCC .isprime        ; is a prime (shortcut to get list started)
85 64       STA $64             ; store to temp as numerator
B1 FB       LDA ($FB),Y         ; load from prime number table
85 65       STA $65             ; store to temp as divisor
A9 00       LDA #$00            ; init modulo to 0
A2 08       LDX #$08            ; iterate over 8 bits
 .bitloop:
06 64       ASL $64             ; shift left numerator
2A          ROL A               ; shift carry into modulo
C5 65       CMP $65             ; compare with divisor
90 02       BCC .bitnext        ; smaller -> to next bit
E5 65       SBC $65             ; otherwise subtract divisor
 .bitnext:
CA          DEX                 ; next bit
D0 F4       BNE .bitloop
C9 00       CMP #$00            ; compare modulo with 0
F0 DC       BEQ .mainnext       ; equal? -> no prime number
C8          INY                 ; next index in prime number table
C4 FE       CPY $FE             ; checked against all prime numbers?
D0 DB       BNE .primecheckloop ; no -> check next
 .isprime:
A5 FD       LDA $FD             ; prime found
A4 FE       LDY $FE             ; then store in table
91 FB       STA ($FB),Y
C8          INY                 ; increment number of primes found
D0 C8       BNE .mainloop       ; and repeat whole process
 .sum:
A9 00       LDA #$00            ; initialize sum to 0
18          CLC
A8          TAY                 ; start adding table from position 0
 .sumloop:
C4 FE       CPY $FE             ; whole table added?
F0 05       BEQ .done           ; yes -> we're done
71 FB       ADC ($FB),Y         ; add current entry
C8          INY                 ; increment index
D0 F7       BNE .sumloop        ; and repeat
 .done:
60          RTS

Ví dụ chương trình biên dịch chương trình C64 sử dụng thường trình:

Bản demo trực tuyến

Mã theo cú pháp ca65 :

.import primesum   ; link with routine above

.segment "BHDR" ; BASIC header
                .word   $0801           ; load address
                .word   $080b           ; pointer next BASIC line
                .word   2018            ; line number
                .byte   $9e             ; BASIC token "SYS"
                .byte   "2061",$0,$0,$0 ; 2061 ($080d) and terminating 0 bytes

.bss
linebuf:        .res    4               ; maximum length of a valid unsigned
                                        ; 8-bit number input
convbuf:        .res    3               ; 3 BCD digits for unsigned 8-bit
                                        ; number conversion
primebuf:       .res    $100            ; buffer for primesum function

.data
prompt:         .byte   "> ", $0
errmsg:         .byte   "Error parsing number, try again.", $d, $0

.code
                lda     #$17            ; set upper/lower mode
                sta     $d018

input:
                lda     #<prompt        ; display prompt
                ldy     #>prompt
                jsr     $ab1e

                lda     #<linebuf       ; read string into buffer
                ldy     #>linebuf
                ldx     #4
                jsr     readline

                lda     linebuf         ; empty line?
                beq     input           ; try again

                lda     #<linebuf       ; convert input to int8
                ldy     #>linebuf
                jsr     touint8
                bcc     numok           ; successful -> start processing
                lda     #<errmsg        ; else show error message and repeat
                ldy     #>errmsg
                jsr     $ab1e
                bcs     input

numok:          
                sta     $2
                lda     #<primebuf
                sta     $fb
                lda     #>primebuf
                sta     $fc
                jsr     primesum        ; call function to sum primes
                tax                     ; and ...
                lda     #$0             ; 
                jmp     $bdcd           ; .. print result

; read a line of input from keyboard, terminate it with 0
; expects pointer to input buffer in A/Y, buffer length in X
.proc readline
                dex
                stx     $fb
                sta     $fc
                sty     $fd
                ldy     #$0
                sty     $cc             ; enable cursor blinking
                sty     $fe             ; temporary for loop variable
getkey:         jsr     $f142           ; get character from keyboard
                beq     getkey
                sta     $2              ; save to temporary
                and     #$7f
                cmp     #$20            ; check for control character
                bcs     checkout        ; no -> check buffer size
                cmp     #$d             ; was it enter/return?
                beq     prepout         ; -> normal flow
                cmp     #$14            ; was it backspace/delete?
                bne     getkey          ; if not, get next char
                lda     $fe             ; check current index
                beq     getkey          ; zero -> backspace not possible
                bne     prepout         ; skip checking buffer size for bs
checkout:       lda     $fe             ; buffer index
                cmp     $fb             ; check against buffer size
                beq     getkey          ; if it would overflow, loop again
prepout:        sei                     ; no interrupts
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and clear 
                and     #$7f            ;   cursor in
                sta     ($d1),y         ;   current row
output:         lda     $2              ; load character
                jsr     $e716           ;   and output
                ldx     $cf             ; check cursor phase
                beq     store           ; invisible -> to store
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and show
                ora     #$80            ;   cursor in
                sta     ($d1),y         ;   current row
                lda     $2              ; load character
store:          cli                     ; enable interrupts
                cmp     #$14            ; was it backspace/delete?
                beq     backspace       ; to backspace handling code
                cmp     #$d             ; was it enter/return?
                beq     done            ; then we're done.
                ldy     $fe             ; load buffer index
                sta     ($fc),y         ; store character in buffer
                iny                     ; advance buffer index
                sty     $fe
                bne     getkey          ; not zero -> ok
done:           lda     #$0             ; terminate string in buffer with zero
                ldy     $fe             ; get buffer index
                sta     ($fc),y         ; store terminator in buffer
                sei                     ; no interrupts
                ldy     $d3             ; get current screen column
                lda     ($d1),y         ; and clear 
                and     #$7f            ;   cursor in
                sta     ($d1),y         ;   current row
                inc     $cc             ; disable cursor blinking
                cli                     ; enable interrupts
                rts                     ; return
backspace:      dec     $fe             ; decrement buffer index
                bcs     getkey          ; and get next key
.endproc

; parse / convert uint8 number using a BCD representation and double-dabble
.proc touint8
                sta     $fb
                sty     $fc
                ldy     #$0
                sty     convbuf
                sty     convbuf+1
                sty     convbuf+2
scanloop:       lda     ($fb),y
                beq     copy
                iny
                cmp     #$20
                beq     scanloop
                cmp     #$30
                bcc     error
                cmp     #$3a
                bcs     error
                bcc     scanloop
error:          sec
                rts
copy:           dey
                bmi     error
                ldx     #$2
copyloop:       lda     ($fb),y
                cmp     #$30
                bcc     copynext
                cmp     #$3a
                bcs     copynext
                sec
                sbc     #$30
                sta     convbuf,x
                dex
copynext:       dey
                bpl     copyloop
                lda     #$0
                sta     $fb
                ldx     #$8
loop:           lsr     convbuf
                lda     convbuf+1
                bcc     skipbit1
                ora     #$10
skipbit1:       lsr     a
                sta     convbuf+1
                lda     convbuf+2
                bcc     skipbit2
                ora     #$10
skipbit2:       lsr     a
                sta     convbuf+2
                ror     $fb
                dex
                beq     done
                lda     convbuf
                cmp     #$8
                bmi     nosub1
                sbc     #$3
                sta     convbuf
nosub1:         lda     convbuf+1
                cmp     #$8
                bmi     nosub2
                sbc     #$3
                sta     convbuf+1
nosub2:         lda     convbuf+2
                cmp     #$8
                bmi     loop
                sbc     #$3
                sta     convbuf+2
                bcs     loop
done:           lda     $fb
                clc
                rts
.endproc

4
Tôi thích điều này hơn rất nhiều so với dòng ngôn ngữ chơi gôn liên tục (tôi có thể hoặc không mặc áo phông MOS 6502 ngày hôm nay).
Matt Lacey

1
@MattLacey cảm ơn :) Tôi quá lười để học tất cả các ngôn ngữ này ... và thực hiện một số câu đố trong mã 6502 cảm thấy hơi "tự nhiên" vì tiết kiệm không gian thực sự là một cách lập trình chuẩn trên chip đó :)
Felix Palmen

Tôi cần mua áo thun MOS 6502.
Tít

8

Python 2 , 49 byte

f=lambda n,t=1,p=1:n and p%t*t+f(n-p%t,t+1,p*t*t)

Sử dụng định lý Wilson , (như được giới thiệu đến trang web của xnor, tôi tin ở đây )

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

Hàm fnày được đệ quy, với đầu vào ban đầu là nvà đuôi khi nđạt đến 0, mang lại số 0 (do logic and); nđược giảm bất cứ khi nào t, một số kiểm tra tăng theo mỗi cuộc gọi đến f, là số nguyên tố. Bài kiểm tra chính là liệu mà chúng tôi theo dõi một hình vuông của giai thừa.(n1)!  1(modn)p


Tôi đã điều chỉnh một trong những chức năng trợ giúp chung của Lynn và đạt được điều tương tự.
Ông Xcoder

... ah vì vậy định lý đã được xnor giới thiệu đến trang web. Bài viết tham khảo tốt, cảm ơn!
Jonathan Allan



6

Java 8, 89 byte

n->{int r=0,i=2,t,x;for(;n>0;r+=t>1?t+0*n--:0)for(t=i++,x=2;x<t;t=t%x++<1?0:t);return r;}

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

Giải trình:

n->{               // Method with integer as both parameter and return-type
  int r=0,         //  Result-sum, starting at 0
      i=2,         //  Prime-integer, starting at 2
      t,x;         //  Temp integers
  for(;n>0         //  Loop as long as `n` is still larger than 0
      ;            //    After every iteration:
       r+=t>1?     //     If `t` is larger than 1 (which means `t` is a prime):
           t       //      Increase `r` by `t`
           +0*n--  //      And decrease `n` by 1
          :        //     Else:
           0)      //      Both `r` and `n` remain the same
    for(t=i++,     //   Set `t` to the current `i`, and increase `i` by 1 afterwards
        x=2;       //   Set `x` to 2
        x<t;       //   Loop as long as `x` is still smaller than `t`
      t=t%x++<1?   //    If `t` is divisible by `x`:
         0         //     Set `t` to 0
        :          //    Else:
         t);       //     `t` remains the same
                   //   If `t` is still the same after this loop, it means it's a prime
  return r;}       //  Return the result-sum



5

Brachylog , 8 7 byte

~lṗᵐ≠≜+

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

Đã lưu 1 byte nhờ @sundar.

Giải trình

~l        Create a list of length input
  ṗᵐ      Each element of the list must be prime
    ≠     All elements must be distinct
     ≜    Find values that match those constraints
      +   Sum

~lṗᵐ≠≜+dường như hoạt động, với 7 byte (Ngoài ra, tôi tò mò tại sao nó lại cho đầu ra 2 * đầu vào + 1 nếu chạy mà không có nhãn.)
sundar - Phục hồi Monica

2
@sundar Tôi đã kiểm tra bằng cách sử dụng trình gỡ lỗi và tìm thấy lý do tại sao: nó không chọn các giá trị cho các số nguyên tố, nhưng nó vẫn biết rằng mọi thứ đều phải [2,+inf)rõ ràng. Do đó, nó biết rằng ít nhất là 5 số nguyên tố (nếu đầu vào là 5) ít nhất 10và một phần biết rằng vì các phần tử phải khác nhau, tất cả chúng không thể là 2 nên ít nhất là 2 11. TL; DR thực hiện labellization ngầm không đủ mạnh.
Gây tử vong vào

Thật là thú vị. Tôi thích làm thế nào lý do không phải là một số cú pháp hoặc sự cố ngẫu nhiên khi thực hiện, nhưng một cái gì đó có ý nghĩa dựa trên các ràng buộc. Cảm ơn vì đã kiểm tra nó!
- Phục hồi lại



2

Võng mạc , 41 byte

K`_
"$+"{`$
$%"_
)/¶(__+)\1+$/+`$
_
^_

_

Hãy thử trực tuyến! Tôi muốn tiếp tục thêm 1 cho đến khi tôi tìm thấy các nsố nguyên tố nhưng tôi không thể tìm ra cách thực hiện điều đó ở Retina vì vậy tôi đã dùng đến một vòng lặp lồng nhau. Giải trình:

K`_

Bắt đầu với 1.

"$+"{`

Vòng lặp nthời gian.

$
$%"_

Tạo một bản sao của giá trị trước đó và tăng nó.

)/¶(__+)\1+$/+`$
_

Tiếp tục tăng nó trong khi nó là tổng hợp. ( )Đóng vòng lặp bên ngoài.)

^_

Xóa bản gốc 1.

_

Tổng và chuyển thành số thập phân.



2

PHP, 66 byte

sử dụng chức năng chính của riêng tôi một lần nữa ...

for(;$k<$argn;$i-1||$s+=$n+!++$k)for($i=++$n;--$i&&$n%$i;);echo$s;

Chạy như ống với -nrhoặc thử trực tuyến .

phá vỡ

for(;$k<$argn;      # while counter < argument
    $i-1||              # 3. if divisor is 1 (e.g. $n is prime)
        $s+=$n              # add $n to sum
        +!++$k              # and increment counter
    )
    for($i=++$n;        # 1. increment $n
        --$i&&$n%$i;);  # 2. find largest divisor of $n smaller than $n:
echo$s;             # print sum

cùng chiều dài, một biến ít hơn:for(;$argn;$i-1||$s+=$n+!$argn--)for($i=++$n;--$i&&$n%$i;);echo$s;
Tít

2

Haskell , 48 byte

sum.(`take`[p|p<-[2..],all((>0).mod p)[2..p-1]])

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

Lưu ý: \p-> all((>0).mod p)[2..p-1] không phải là kiểm tra chính hợp lệ, vì nó Truedành cho0,1cũng. Nhưng chúng ta có thể làm việc xung quanh đó bằng cách bắt đầu với2, vì vậy trong trường hợp này nó đủ.



2

C, C ++, D: 147 142 byte

int p(int a){if(a<4)return 1;for(int i=2;i<a;++i)if(!(a%i))return 0;return 1;}int f(int n){int c=0,v=1;while(n)if(p(++v)){c+=v;--n;}return c;}

Tối ưu hóa 5 byte cho C và C ++:

-2 byte nhờ Zacharý

#define R return
int p(int a){if(a<4)R 1;for(int i=2;i<a;++i)if(!(a%i))R 0;R 1;}int f(int n){int c=0,v=1;while(n)if(p(++v))c+=v,--n;R c;}

pkiểm tra nếu một số là số nguyên tố, tính ftổng các nsố đầu tiên

Mã được sử dụng để kiểm tra:

C / C ++:

for (int i = 0; i < 10; ++i)
    printf("%d => %d\n", i, f(i));

D Câu trả lời được tối ưu hóa bởi Zacharý , 133 131 byte

D có một hệ thống mẫu golf

T p(T)(T a){if(a<4)return 1;for(T i=2;i<a;)if(!(a%i++))return 0;return 1;}T f(T)(T n){T c,v=1;while(n)if(p(++v))c+=v,--n;return c;}

1
T p(T)(T a){if(a<4)return 1;for(T i=2;i<a;)if(!(a%i++))return 0;return 1;}T f(T)(T n){T c,v=1;while(n)if(p(++v)){c+=v;--n;}return c;}. Ngoài ra, C / C ++ / D có thể int p(int a){if(a<4)return 1;for(int i=2;i<a;++i)if(!(a%i))return 0;return 1;}int f(int n){int c=0,v=1;while(n)if(p(++v)){c+=v;--n;}return c;}(giống với tối ưu hóa C / C ++, chỉ cần điều chỉnh thuật toán abit)
Zacharý

Có lẽ đối với tất cả các câu trả lời, bạn có thể sử dụng dấu phẩy để làm {c+=v;--n;}được c+=v,--n;?
Zacharý

Đây là một cái khác cho D (và có thể cho C / C ++, nếu được hoàn nguyên về ints):T p(T)(T a){T r=1,i=2;for(;i<a;)r=a%i++?r:0;return r;}T f(T)(T n){T c,v=1;while(n)if(p(++v))c+=v,--n;return c;}
Zacharý

Đề xuất a>3&i<athay i<avà xóaif(a<4)...
trần mèo

2

Japt -x , 11 byte

;@_j}a°X}hA

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

Đã lưu một vài byte nhờ một tính năng ngôn ngữ mới.

Giải trình:

;@      }hA    :Get the first n numbers in the sequence:
     a         : Get the smallest number
      °X       : Which is greater than the previous result
  _j}          : And is prime
               :Implicitly output the sum



1

APL (Dyalog Unicode) , 7 + 9 = 16 byte

+/pco∘⍳

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

9 byte bổ sung để nhập pcoDfn (và mọi loại khác):⎕CY'dfns'

Làm sao:

+/pco∘⍳
        Generate the range from 1 to the argument
        Compose
  pco    P-colon (p:); without a left argument, it generates the first <right_arg> primes.
+/       Sum

Bạn không phải thêm một byte nữa? import X(dòng mới) X.something()trong python được tính với dòng mới.
Zacharý

1

Ruby, 22 + 7 = 29 byte

Chạy với ruby -rprime(+7)

->n{Prime.take(n).sum}


1

JAEL , 5 byte

#&kȦ

Giải thích (được tạo tự động):

./jael --explain '#&kȦ'
ORIGINAL CODE:  #&kȦ

EXPANDING EXPLANATION:
Ȧ => .a!

EXPANDED CODE:  #&k.a!,

#     ,                 repeat (p1) times:
 &                              push number of iterations of this loop
  k                             push nth prime
   .                            push the value under the tape head
    a                           push p1 + p2
     !                          write p1 to the tape head
       ␄                print machine state



0

CJam , 21 byte

0{{T1+:Tmp!}gT}li*]:+


Explanation:
0{{T1+:Tmp!}gT}li*]:+ Original code

 {            }li*    Repeat n times
  {        }          Block
   T                  Get variable T | stack: T
    1+                Add one | Stack: T+1 
      :T              Store in variable T | Stack: T+1
        mp!           Is T not prime?     | Stack: !(isprime(T))
            g         Do while condition at top of stack is true, pop condition
             T        Push T onto the stack | Stack: Primes so far
0                 ]   Make everything on stack into an array, starting with 0 (to not throw error if n = 0)| Stack: array with 0 and all primes up to n
                   :+ Add everything in array

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


0

F #, 111 byte

let f n=Seq.initInfinite id|>Seq.filter(fun p->p>1&&Seq.exists(fun x->p%x=0){2..p-1}|>not)|>Seq.take n|>Seq.sum

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

Seq.initInfinitetạo ra một chuỗi dài vô tận với hàm tạo, lấy tham số là chỉ mục vật phẩm. Trong trường hợp này, hàm tạo chỉ là hàm nhận dạng id.

Seq.filter chỉ chọn các số được tạo bởi chuỗi vô hạn là số nguyên tố.

Seq.takelấy các nyếu tố đầu tiên trong chuỗi đó.

Và cuối cùng, Seq.sumtổng hợp chúng lên.



0

TÔI , 4 byte

⎕ṀΣ↵

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

Vẫn hối tiếc vì không có đầu vào / đầu ra ngầm định trong ngôn ngữ rác này, nếu không sẽ là hai byte.

  • = đầu vào
  • = 1 ... bao gồm số nguyên tố thứ n
  • Σ = tổng
  • = đầu ra

0

APL (NARS), 27 ký tự, 54 byte

{⍵=0:0⋄+/{⍵=1:2⋄¯2π⍵-1}¨⍳⍵}

{2π⍵} ở đây sẽ trả về số nguyên tố n khác với 2. Vì vậy, {= 1: 2⋄¯2π⍵ - 1} sẽ trả về số nguyên tố n 2 trong số đó ...

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.