计算前n个质数的总和


15

令我惊讶的是,这一挑战已经很明显了。(或者我很惊讶我找不到它,任何人都会将其标记为重复。)

任务

给定一个非负整数,计算前素数的总和并输出。nnn

例子1

对于n=5,前五个素数为:

  • 2
  • 3
  • 5
  • 7
  • 11

这些数字的总和是2+3+5+7+11=28,因此程序必须输出28

范例#2

对于n=0,“第一个零”素数为空。没有数字的总和-当然是0

规则

  • 您可以使用内置函数,例如,检查数字是否为质数。
  • 这是,因此每种语言中的最低字节数为准!



2
OEIS-A7504 (除了:在公式部分中的LOL,“ a(n)= A033286(n)-A152535(n)”。)
乔纳森·艾伦

@JonathanAllan:相关,但不等同。我认为如果您检查范围内的质数或多个质数,这是一个重要的区别。这两个任务的共同点是:a)检查数字是否为质数; b)求和(在这里,这是许多代码高尔夫任务所共有的)。
xanoetux

Answers:


15

6502机器代码例程,75字节

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

期望在$fb/中有指向临时存储的指针,$fc并在中总结素数$2。返回总和A(累加寄存器)。

从来没有对6502机器代码进行过任何素数检查,所以终于来了;)

请注意,这开始为输入> = 14给出错误的结果。这是由于溢出造成的,该代码使用8bit平台的“自然”数字范围(0 - 255用于unsigned)工作

评论拆解

; 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

使用例程的示例C64汇编程序:

在线演示

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
我不仅仅喜欢持续不断的打高尔夫球,还喜欢这种语言(今天我可能会或可能不会穿着MOS 6502 T恤)。
马特·莱西

1
@MattLacey谢谢:)我懒得学习所有这些语言...并且在6502代码中做一些困惑感觉有点“自然”,因为节省空间实际上是该芯片上的标准编程习惯:)
Felix Palmen

我需要购买MOS 6502 T恤。
泰特斯

8

Python 2,49个字节

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

使用威尔逊定理(由xnor引入网站,我相信在这里

在线尝试!

该函数f是递归的,初始输入为nn到达零时为尾,产生零(由于逻辑and);n只要t,每次调用时都会增加的测试数f是素数,就将减小。首要的检验是(n1)!  1(modn)p


我正在改编Lynn的常用帮助函数之一,并实现了完全相同的功能
Xcoder先生

...啊,所以定理由xnor引入了现场。好的参考帖子,谢谢!
乔纳森·艾伦



6

Java 8,89字节

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

在线尝试。

说明:

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

Brachylog8 7字节

~lṗᵐ≠≜+

在线尝试!

感谢@sundar,节省了1个字节。

说明

~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ṗᵐ≠≜+似乎有效,为7个字节(另外,我很好奇,如果运行时不带标签,为什么它会给出输出2 * input + 1。)
sundar-恢复莫妮卡

2
@sundar我使用调试器进行了检查,发现了原因:它没有选择素数的值,但它仍然知道[2,+inf)显然每个元素都必须存在。因此,它知道5个质数之和(如果输入为5)必须至少为10,并且部分知道由于元素必须不同,所以它们不能全部为2,因此至少为11。TL; DR隐式标签实现的功能不够强大。
致命的

那很有趣。我喜欢原因不是语法上的古怪或实现的偶​​然性,而是基于约束的意义。感谢检查出来!
sundar-恢复莫妮卡



2

视网膜,41字节

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

_

在线尝试!我一直想加1,直到找到n素数,但是我无法弄清楚在Retina中怎么做,所以我求助于嵌套循环。说明:

K`_

从1开始

"$+"{`

循环n时间。

$
$%"_

复制前一个值,然后增加它。

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

在复合时不断增加它。()关闭外部循环。)

^_

删除原件1

_

求和并转换为十进制。



2

PHP,66字节

再次使用我自己的质数函数 ...

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

与管道一起运行-nr在线尝试

分解

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

相同的长度,少一个变量:for(;$argn;$i-1||$s+=$n+!$argn--)for($i=++$n;--$i&&$n%$i;);echo$s;
Titus

2

Haskell,48个字节

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

在线尝试!

注意: \p-> all((>0).mod p)[2..p-1]这不是有效的素数检查,因为它True用于01个也一样 但我们可以通过以下方法解决此问题2,因此在这种情况下就足够了。



2

C,C ++,D:147142字节

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

C和C ++的5字节优化:

-2个字节,感谢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;}

p测试数字是否为质数,f将第n一个数字求和

用于测试的代码:

C / C ++:

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

d优化答案由扎卡里133个 131字节

D具有高尔夫球样板系统

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;}。另外,C / C ++ / d可以是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;}(相同与C / C ++优化,只是调整算法升技)
扎卡里

也许对于所有答案,您都可以使用逗号使{c+=v;--n;}be成为c+=v,--n;
扎卡里

这是D的另一个(如果还回到ints ,也可能是C / C ++ ):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ý18年

建议a>3&i<a而不是i<a删除if(a<4)...
ceilingcat '18

2

Japt -x,11个字节

;@_j}a°X}hA

在线尝试!

有了新的语言功能,节省了几个字节。

说明:

;@      }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个字节

+/pco∘⍳

在线尝试!

9个额外的字节来导入pco(以及每隔一个)Dfn:⎕CY'dfns'

怎么样:

+/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

您是否不必再添加一个字节?python中的import X(newline)X.something()被换行计数。
扎卡里

1

Ruby,22 + 7 = 29个字节

运行ruby -rprime(+7)

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


1

JAEL,5个字节

#&kȦ

说明(自动生成):

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

Python 2中63个 59 56 51字节

f=lambda n:n and prime(n)+f(n-1)
from sympy import*

在线尝试!


已保存:

  • -5个字节,感谢Jonathan Allan

没有库:

Python 2,83个字节

n,s=input(),0
x=2
while n:
 if all(x%i for i in range(2,x)):n-=1;s+=x
 x+=1
print s

在线尝试!


f=lambda n:n and prime(n)+f(n-1)节省五分(可能也可以打高尔夫球)
乔纳森·艾伦


0

CJam,21个字节

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

在线尝试!


0

F#,111个字节

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

在线尝试!

Seq.initInfinite使用生成器函数创建一个无限长的序列,该函数将项索引作为参数。在这种情况下,生成器函数就是身份函数id

Seq.filter 仅选择由无限序列创建的质数。

Seq.take 首先 n顺序中元素。

最后,Seq.sum总结一下。



0

MY,4个字节

⎕ṀΣ↵

在线尝试!

仍然遗憾的是,在这种垃圾语言中没有隐式的输入/输出,否则将是两个字节。

  • =输入
  • = 1 ...包含第n个素数
  • Σ =总和
  • =输出

0

APL(NARS),27个字符,54个字节

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

{¯2π⍵}将返回不同于2的n个素数。因此{So = 1:2⋄¯2π⍵-1}将返回其中的n个素数2 ...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.