Вычислить сумму первых n простых чисел


15

Я удивлен, что этот вызов еще не здесь, так как это так очевидно. (Или я удивлен, что не смог найти его, и кто-нибудь пометит его как дубликат.)

задача

Если задано неотрицательное целое число N , вычислите сумму первых N простых чисел и выведите ее.

Пример № 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: Связано, но не эквивалентно. Я думаю, что это важное различие, если вы проверяете простые числа в диапазоне или число простых чисел. Обе задачи имеют общее: а) проверка, является ли число простым, и б) суммирование чисел - что является общим для многих задач по коду в гольф.
xanoetux

Ответы:


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. Это из-за переполнения, код работает с «натуральным» диапазоном чисел 8-битной платформы, которая предназначена 0 - 255для беззнаковых .

Прокомментировал разборку

; 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).
Мэтт Лэйси,

1
@MattLacey спасибо :) Мне просто лень изучать все эти языки ... и делать некоторые загадки в коде 6502 кажется "естественным", потому что экономия места на самом деле является стандартной практикой программирования на этом чипе :)
Феликс Палмен

Мне нужно купить футболку MOS 6502.
Тит

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является рекурсивной, с начальным вводом nи хвостом, когда nдостигает нуля, что дает этот ноль (из-за логического and); nуменьшается каждый раз t, когда тестовое число, которое увеличивается с каждым вызовом f, является простым. Тогда основной тест - это для которого мы отслеживаем квадрат факториала в.(N-1)!  -1(модификацияN)p


Я адаптировал одну из общих вспомогательных функций Линн и достиг того же самого.
Мистер Кскодер

... ах, так что теорема была введена на сайт 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

Брахилог , 8 7 байт

~lṗᵐ≠≜+

Попробуйте онлайн!

Сохранено 1 байт благодаря @sundar.

объяснение

~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 - Восстановить Monica

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;
Тит



2

C, C ++, D: 147 142 байта

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

5-байтовая оптимизация для C и C ++:

-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 Оптимизированный ответ Zacharý , 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 ++, просто настраивая алгоритм abit)
Zacharý

Может быть, для всех ответов, вы можете использовать запятую, чтобы {c+=v;--n;}быть c+=v,--n;?
Захари

Вот еще один для D (и, возможно, для C / C ++, если вернуться к 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;}
Захари

Предложить a>3&i<aвместо i<aи удалитьif(a<4)...
потолок кошка

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

Вам не нужно добавлять еще один байт? import X(новая строка) X.something()в python считается с новой строки.
Захари



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 байт, благодаря Джонатану Аллану

Без библиотек:

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

МОЙ , 4 байта

⎕ṀΣ↵

Попробуйте онлайн!

Все еще сожалея об отсутствии неявного ввода / вывода на этом языке мусора, иначе было бы два байта.

  • = вход
  • = 1-е ... пятое простое включительно
  • Σ = сумма
  • = выход

0

APL (NARS), 27 символов, 54 байта

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

{¯2π⍵} здесь вернул бы n простых чисел, отличных от 2. Так что {⍵ = 1: 2⋄¯2π⍵-1} вернул бы n простых чисел 2 в нем ...

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.