Hana 9e216da9ef go.mod: add go.mod and move pygments to third_party
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.
2021-02-15 16:45:26 -05:00

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