令我惊讶的是,这一挑战已经很明显了。(或者我很惊讶我找不到它,任何人都会将其标记为重复。)
任务
给定一个非负整数,计算前素数的总和并输出。n
例子1
对于,前五个素数为:
- 2
- 3
- 5
- 7
- 11
这些数字的总和是,因此程序必须输出。
范例#2
对于,“第一个零”素数为空。没有数字的总和-当然是。
规则
- 您可以使用内置函数,例如,检查数字是否为质数。
- 这是代码高尔夫球,因此每种语言中的最低字节数为准!
令我惊讶的是,这一挑战已经很明显了。(或者我很惊讶我找不到它,任何人都会将其标记为重复。)
给定一个非负整数,计算前素数的总和并输出。n
对于,前五个素数为:
这些数字的总和是,因此程序必须输出。
对于,“第一个零”素数为空。没有数字的总和-当然是。
Answers:
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
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
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
~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。)
[2,+inf)
显然每个元素都必须存在。因此,它知道5个质数之和(如果输入为5)必须至少为10
,并且部分知道由于元素必须不同,所以它们不能全部为2,因此至少为11
。TL; DR隐式标签实现的功能不够强大。
再次使用我自己的质数函数 ...
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;
n=s
而不是return s
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;}
-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具有高尔夫球样板系统
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;}
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;
?
int
s ,也可能是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;}
a>3&i<a
而不是i<a
删除if(a<4)...
-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
+/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
(newline)X.something()
被换行计数。
#&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{{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