
After go1.16, go will use module mode by default, even when the repository is checked out under GOPATH or in a one-off directory. Add go.mod, go.sum to keep this repo buildable without opting out of the module mode. > go mod init github.com/mmcgrana/gobyexample > go mod tidy > go mod vendor In module mode, the 'vendor' directory is special and its contents will be actively maintained by the go command. pygments aren't the dependency the go will know about, so it will delete the contents from vendor directory. Move it to `third_party` directory now. And, vendor the blackfriday package. Note: the tutorial contents are not affected by the change in go1.16 because all the examples in this tutorial ask users to run the go command with the explicit list of files to be compiled (e.g. `go run hello-world.go` or `go build command-line-arguments.go`). When the source list is provided, the go command does not have to compute the build list and whether it's running in GOPATH mode or module mode becomes irrelevant.
285 lines
4.7 KiB
Plaintext
285 lines
4.7 KiB
Plaintext
;--------------------------------------
|
|
; Lychrel numbers.
|
|
;
|
|
; :author: Marc 'BlackJack' Rintsch
|
|
; :date: 2008-03-07
|
|
; :version: 0.1
|
|
;
|
|
; Prints all `Lychrel numbers`_ between 1 and 100000.
|
|
;
|
|
; The numbers are stored as array of "digits" in little endian
|
|
; order. Each digit is a byte with a value between 0 and 9.
|
|
;
|
|
; Runtime on C64: 00:21:01
|
|
;
|
|
; .. _Lychrel numbers: http://en.wikipedia.org/wiki/Lychrel_number
|
|
;
|
|
; .. cl65 -l -tnone -C simple.cfg lychrel.s -o lychrel.prg
|
|
;--------------------------------------
|
|
|
|
;--------------------------------------
|
|
; External addresses.
|
|
;--------------------------------------
|
|
chrout = $ffd2
|
|
|
|
;--------------------------------------
|
|
; Constants.
|
|
;--------------------------------------
|
|
TO = 100000
|
|
TO_DIGITS = 10
|
|
ITERATIONS = 100
|
|
MAX_DIGITS = TO_DIGITS + ITERATIONS
|
|
|
|
;--------------------------------------
|
|
; Global variables.
|
|
;--------------------------------------
|
|
.zeropage
|
|
;
|
|
; Length of the currently tested `n` in digits.
|
|
;
|
|
n_length:
|
|
.res 1
|
|
;
|
|
; Length of the number(s) `xa` and `xb` while testing.
|
|
;
|
|
length:
|
|
.res 1
|
|
|
|
.bss
|
|
;
|
|
; Number to be tested as digits i.e. bytes with values between
|
|
; 0 and 9. The length is stored in `n_length`.
|
|
;
|
|
n:
|
|
.res TO_DIGITS
|
|
;
|
|
; Space for calculating the reversed and added values.
|
|
; In the `main` code the current number is copied into `xa`
|
|
; and then repeatedly `reverse_add`\ed to itself with the
|
|
; result of that adding stored in `xb`.
|
|
;
|
|
xa:
|
|
.res MAX_DIGITS
|
|
xb:
|
|
.res MAX_DIGITS
|
|
|
|
;--------------------------------------
|
|
; BASIC header.
|
|
;--------------------------------------
|
|
.code
|
|
.word 0800h ; Load address.
|
|
.byte 0
|
|
.word @line_end
|
|
.word 2008 ; Line number.
|
|
.byte $9e ; SYS token.
|
|
.byte "2080 " ; SYS argument.
|
|
.byte "LYCHREL NUMBERS/BJ"
|
|
@line_end:
|
|
.byte 0, 0, 0 ; Line and program end marker.
|
|
|
|
;--------------------------------------
|
|
; Main program.
|
|
;--------------------------------------
|
|
.proc main
|
|
|
|
.zeropage
|
|
;
|
|
; Three byte counter for `TO` iterations (100000 = $0186a0).
|
|
;
|
|
i:
|
|
.res 3
|
|
|
|
.code
|
|
;
|
|
; Clear and set `n` and `i` to 1.
|
|
;
|
|
lda #0 ; n := 0; n := 1; i := 1
|
|
sta i+1
|
|
sta i+2
|
|
ldx #TO_DIGITS
|
|
clear_n:
|
|
sta n-1,x
|
|
dex
|
|
bne clear_n
|
|
inx
|
|
stx i
|
|
stx n
|
|
stx n_length
|
|
|
|
mainloop:
|
|
jsr is_lychrel
|
|
bcc no_lychrel
|
|
jsr print_n
|
|
no_lychrel:
|
|
jsr increase_n
|
|
|
|
inc i ; INC(i)
|
|
bne skip
|
|
inc i+1
|
|
bne skip
|
|
inc i+2
|
|
skip:
|
|
lda i
|
|
cmp #<TO
|
|
bne mainloop
|
|
lda i+1
|
|
cmp #>TO
|
|
bne mainloop
|
|
lda i+2
|
|
cmp #^TO
|
|
bne mainloop
|
|
|
|
rts
|
|
.endproc
|
|
|
|
;--------------------------------------
|
|
; Print `n` and a trailing newline.
|
|
;
|
|
; :in: `n_length`, `n`
|
|
;--------------------------------------
|
|
.proc print_n
|
|
ldy n_length
|
|
L1:
|
|
lda n-1,y
|
|
ora #%110000 ; = '0'
|
|
jsr chrout
|
|
dey
|
|
bne L1
|
|
|
|
lda #13
|
|
jmp chrout
|
|
.endproc
|
|
|
|
;--------------------------------------
|
|
; Increase `n` by one.
|
|
;
|
|
; This procedure expects n[n_length] == 0 in case the number gets
|
|
; one digit longer.
|
|
;
|
|
; :in: `n`, `n_length`
|
|
; :out: `n`, `n_length`
|
|
;--------------------------------------
|
|
.proc increase_n
|
|
ldx #0
|
|
L1:
|
|
inc n,x ; Increase digit.
|
|
lda n,x
|
|
cmp #10 ; If "carry", store 0 and go to next digit.
|
|
bne return
|
|
lda #0
|
|
sta n,x
|
|
inx
|
|
bne L1
|
|
return:
|
|
cpx n_length ; If "carry" after last digit, increase length.
|
|
bcc skip
|
|
inc n_length
|
|
skip:
|
|
rts
|
|
.endproc
|
|
|
|
;--------------------------------------
|
|
; Tests if `n` is a Lychrel number.
|
|
;
|
|
; :in: `n`, `n_length`
|
|
; :out: C is set if yes, cleared otherwise.
|
|
; :uses: `length`, `xa`, `xb`
|
|
;--------------------------------------
|
|
.proc is_lychrel
|
|
.zeropage
|
|
i:
|
|
.res 1
|
|
|
|
.code
|
|
ldx n_length ; xa := n; length := n_length
|
|
stx length
|
|
L1:
|
|
lda n-1,x
|
|
sta xa-1,x
|
|
dex
|
|
bne L1
|
|
|
|
lda #ITERATIONS ; i := ITERATIONS
|
|
sta i
|
|
L2:
|
|
jsr reverse_add
|
|
jsr is_palindrome
|
|
bne no_palindrome
|
|
clc
|
|
rts
|
|
no_palindrome:
|
|
ldx length ; a := b
|
|
L3:
|
|
lda xb-1,x
|
|
sta xa-1,x
|
|
dex
|
|
bne L3
|
|
|
|
dec i ; Loop body end.
|
|
bne L2
|
|
|
|
sec
|
|
rts
|
|
.endproc
|
|
|
|
;--------------------------------------
|
|
; Add the reverse to `xa` to itself and store the result in `xb`.
|
|
;
|
|
; :in: `length`, `xa`
|
|
; :out: `length`, `xb`
|
|
;--------------------------------------
|
|
.proc reverse_add
|
|
.code
|
|
ldx #0
|
|
ldy length
|
|
clc
|
|
L1:
|
|
lda xa,x
|
|
adc xa-1,y
|
|
|
|
cmp #10
|
|
bcc no_adjust
|
|
sbc #10
|
|
no_adjust:
|
|
sta xb,x
|
|
|
|
dey
|
|
inx
|
|
txa ; ``eor`` instead of ``cpx`` to keep the carry flag
|
|
eor length ; of the addition above.
|
|
bne L1
|
|
|
|
bcc no_carry
|
|
lda #1
|
|
sta xb,x
|
|
inc length
|
|
no_carry:
|
|
rts
|
|
.endproc
|
|
|
|
;--------------------------------------
|
|
; Checks if `xb` is a palindrome.
|
|
;
|
|
; :in: `length`, `xb`
|
|
; :out: Z flag set if `xb` is a palindrome, cleared otherwise.
|
|
;--------------------------------------
|
|
.proc is_palindrome
|
|
.code
|
|
ldx #0
|
|
lda length
|
|
tay
|
|
lsr
|
|
sta L1+1 ; Self modifying code!
|
|
L1:
|
|
cpx #0 ; <<< 0 replaced by (`length` / 2).
|
|
beq return
|
|
lda xb,x
|
|
cmp xb-1,y
|
|
bne return
|
|
dey
|
|
inx
|
|
bne L1
|
|
return:
|
|
rts
|
|
.endproc
|