Implement binary search tree and base day1a on it

This commit is contained in:
Sijmen 2020-12-09 13:27:21 +01:00
parent 438b622c58
commit 8467b7c9a0
Signed by: vijfhoek
GPG key ID: DAF7821E067D9C48
3 changed files with 208 additions and 81 deletions

106
c64/btree.asm Normal file
View file

@ -0,0 +1,106 @@
// vim: filetype=kickass
.const next_index = $02
.const input = $03
// NOTE Assumes the tree is zeroed
tree_insert:
ldx #0
!loop:
lda tree_values_lo, x
bne !not_zero+
lda tree_values_hi, x
bne !not_zero+
// Insert the node
lda input
sta tree_values_lo, x
lda input + 1
sta tree_values_hi, x
inc next_index
rts
!not_zero:
sec
lda tree_values_lo, x
sbc input
lda tree_values_hi, x
sbc input + 1
bcc !greater+
!less:
lda tree_left, x
bne !+
lda next_index
sta tree_left, x
!:
lda tree_left, x
tax
jmp !loop-
!greater:
lda tree_right, x
bne !+
lda next_index
sta tree_right, x
!:
lda tree_right, x
tax
jmp !loop-
brk
tree_contains:
ldx #0
!loop:
sec
lda tree_values_lo, x
sbc input
beq !lo_eq+
lda tree_values_hi, x
sbc input + 1
bcc !greater+
!less:
lda tree_left, x
beq !not_found+
tax
jmp !loop-
!greater:
lda tree_right, x
beq !not_found+
tax
jmp !loop-
!not_found:
// Match not found, set 1 so bne branches
lda #1
rts
!lo_eq:
lda tree_values_hi, x
sbc input + 1
bne !less-
// Match found, set 0 so beq branches
lda #0
rts
brk
.align $100
tree_values_lo:
.fill 256, 0
tree_values_hi:
.fill 256, 0
tree_left:
.fill 256, 0
tree_right:
.fill 256, 0

View file

@ -9,15 +9,13 @@
// Destroys: // Destroys:
// a, x, y, $02..$04, $10..$1c, $20..$25, $fd..$fe, everything you've ever loved // a, x, y, $02..$04, $10..$1c, $20..$25, $fd..$fe, everything you've ever loved
// //
.const input_pointer = $03 .const input_pointer = $20
.const buffer_pointer = $20 .const atoi_result = $03 // Needs to be $03 for tree_insert
.const atoi_result = $22
.const outer_pointer = $20 .const loop_pointer = $20
.const inner_pointer = $22 .const remainder = $24
.const remainder = $24
// Need to be $03 and $fd due to multiply_16bit_unsigned // Need to be $26 and $fd due to multiply_16bit_unsigned
.const outer_value = $26 .const outer_value = $26
.const inner_value = $fd .const inner_value = $fd
@ -29,7 +27,6 @@ day01:
// Parse the input at day01_input into an array of integers. // Parse the input at day01_input into an array of integers.
// //
move_16_imm(input_pointer, day01_input) move_16_imm(input_pointer, day01_input)
move_16_imm(buffer_pointer, buffer)
ldy #0 ldy #0
!line: !line:
@ -64,26 +61,13 @@ day01:
jmp !digit- jmp !digit-
!newline: !newline:
sty zp_temp // Insert the converted number into the tree.
jsr tree_insert
// Append the result of the conversion to the array.
ldy #0
lda atoi_result + 0
sta (buffer_pointer), y
iny
lda atoi_result + 1
sta (buffer_pointer), y
// Increment the buffer pointer by 2.
lda #2
i16_i8_add_a(buffer_pointer)
ldy zp_temp
iny iny
bne !+ bne !+
inc input_pointer + 1 inc input_pointer + 1
!: !:
// Check for the null terminator. // Check for the null terminator.
lda (input_pointer), y lda (input_pointer), y
@ -92,60 +76,28 @@ day01:
move_16_imm($03, str_parse_done) move_16_imm($03, str_parse_done)
jsr write_string jsr write_string
move_16_imm(outer_pointer, buffer)
// Add every number to every other number
!outer:
move_16_imm(inner_pointer, buffer)
// $03..$04 = buffer[i]
ldy #0 ldy #0
lda (outer_pointer), y !loop:
sta outer_value // Subtract the number from 2020 to find the needed value.
iny lda tree_values_lo, y
lda (outer_pointer), y sta $fd
sta outer_value + 1 eor #$ff
sec
adc #<2020
sta $03
sta $26
dey lda tree_values_hi, y
lda (outer_pointer), y sta $fe
bne !not_zero+ eor #$ff
iny adc #>2020
lda (outer_pointer), y sta $04
bne !not_zero+ sta $27
jmp !error+
!not_zero:
// Subtract from 2020 to see what number we need iny
i16_imm_i16_sub(remainder, 2020, outer_value) jsr tree_contains
bne !loop-
!inner:
// $fd..$fe = buffer[j]
ldy #0
lda (inner_pointer), y
sta inner_value
iny
lda (inner_pointer), y
sta inner_value + 1
dey
lda (inner_pointer), y
bne !not_zero+
iny
lda (inner_pointer), y
bne !not_zero+
i16_inc(outer_pointer)
jmp !outer-
!not_zero:
// j++
lda #2
i16_i8_add_a(inner_pointer)
// Continue the loop if the number didn't match the needed number.
i16_i16_cmp_bne(remainder, inner_value, !inner-)
!done:
// Multiply the results together // Multiply the results together
sec sec
jsr multiply_16bit_unsigned jsr multiply_16bit_unsigned

View file

@ -4,7 +4,7 @@
BasicUpstart2(main) BasicUpstart2(main)
* = $0900 "Main program" * = $1000 "Main program"
.const SCREEN_RAM = $0400 .const SCREEN_RAM = $0400
.const COLOR_RAM = $d800 .const COLOR_RAM = $d800
@ -43,6 +43,77 @@
sta dst + i sta dst + i
} }
} }
test_tree:
move_16_imm($03, !str_test+)
jsr write_string
move_16_imm($03, $10)
jsr tree_insert
move_16_imm($03, $08)
jsr tree_insert
move_16_imm($03, $04)
jsr tree_insert
move_16_imm($03, $12)
jsr tree_insert
move_16_imm($03, $1337)
jsr tree_insert
move_16_imm($03, $08)
jsr tree_contains
bne !fail+
move_16_imm($03, $13)
jsr tree_contains
beq !fail+
move_16_imm($03, $12)
jsr tree_contains
bne !fail+
move_16_imm($03, $1337)
jsr tree_contains
bne !fail+
move_16_imm($03, $0420)
jsr tree_contains
beq !fail+
move_16_imm($03, !str_success+)
jsr write_string
rts
!fail:
u16_u16_move($10, $03)
move_16_imm($03, !str_fail+)
jsr write_string
lda $11
jsr print_hex_0x
lda $10
jsr print_hex
jsr print_newline
rts
!str_test:
.text "[ ] test-tree"
.byte '\r', 0
!str_fail:
.text "[!!]"
.byte '\n'
.text "Failed: "
.byte 0
!str_success:
.text "[OK]"
.byte '\n', 0
// //
// main // main
// //
@ -55,21 +126,19 @@ main:
sta $01 sta $01
jsr generate_multiplication_tables jsr generate_multiplication_tables
//jsr test_tree
jsr day01 jsr day01
!loop: !loop:
jmp !loop- jmp !loop-
buffer:
.fill $0400, 0
#import "day01.asm" #import "day01.asm"
#import "screen.asm" #import "screen.asm"
#import "math.asm" #import "math.asm"
#import "btree.asm"
* = * "Day 01 Input" * = * "Day 01 Input"
day01_input: day01_input: