// vim: filetype=kickass * = * "Day 09 Input" !input: .import text "../inputs/09" .byte 0 * = * "Day 09 Code" day09: { .const buffer = $b000 .const buffer_end = $bfa0 .const input_pointer = $40 // $40..42 .const atoi_result = $42 // $42..46 .const buffer_pointer = $46 // $46..48 .const outer_pointer = $48 // $48..4a .const middle_pointer = $4a // $4a..4c .const inner_pointer = $4c // $4c..4e .const part1 = $4e // $4e..52 .const lower_pointer = $52 // $52..54 .const upper_pointer = $54 // $54..56 .const sum = $56 // $56..5a .const min_value = $5a // $5a..5e .const max_value = $5e // $5e..62 // XXX I'm using 32 bit integers for this day, even though some // inputs are 64 bit. Seems like I get away with it though. move_16_imm($03, !str_title+) jsr write_string move_16_imm(input_pointer, !input-) move_16_imm(buffer_pointer, buffer) ldy #0 !line: // 32-bit integer to store the result in. lda #0 sta atoi_result + 0 sta atoi_result + 1 sta atoi_result + 2 sta atoi_result + 3 !digit: // Check for the newline character at the end of the line. lda (input_pointer), y cmp #'\n' beq !newline+ // Multiply the stored number by 10. u32_mul10(atoi_result) // Subtract '0' from the current digit to convert it to binary. lda (input_pointer), y sec sbc #'0' // Add the binary digit to the stored number i32_add_a(atoi_result) y_buf_inc(input_pointer) jmp !digit- !newline: sty zp_temp ldy #0 lda atoi_result + 0 sta (buffer_pointer), y iny lda atoi_result + 1 sta (buffer_pointer), y iny lda atoi_result + 2 sta (buffer_pointer), y iny lda atoi_result + 3 sta (buffer_pointer), y lda buffer_pointer clc adc #4 sta buffer_pointer bcc !cc+ inc buffer_pointer + 1 !cc: ldy zp_temp y_buf_inc(input_pointer) // Check for the null terminator. lda (input_pointer), y beq !done+ jmp !line- !done: // outer for loop initial value // outer_pointer = buffer + 25 lda #<(buffer + 25 * 4) sta outer_pointer + 0 lda #>(buffer + 25 * 4) sta outer_pointer + 1 !outer: // middle for loop initial value // middle_pointer = outer_pointer - 25 sec lda outer_pointer + 0 sbc #(25 * 4) sta middle_pointer + 0 lda outer_pointer + 1 sbc #0 sta middle_pointer + 1 // TODO if *middle_pointer > *outer_pointer: continue !middle: // inner_pointer = middle_pointer + 1 clc lda middle_pointer + 0 adc #(1 * 4) sta inner_pointer + 0 lda middle_pointer + 1 adc #0 sta inner_pointer + 1 !inner: // if *inner_pointer + *middle_pointer == *outer_pointer: // continue 'outer; // *atoi_result = *inner_pointer + *middle_pointer clc ldy #0 lda (inner_pointer), y adc (middle_pointer), y sta (atoi_result), y iny lda (inner_pointer), y adc (middle_pointer), y sta (atoi_result), y iny lda (inner_pointer), y adc (middle_pointer), y sta (atoi_result), y iny lda (inner_pointer), y adc (middle_pointer), y sta (atoi_result), y // if *atoi_result == *outer_pointer: ldy #0 lda (atoi_result), y cmp (outer_pointer), y bne !not_equal+ iny lda (atoi_result), y cmp (outer_pointer), y bne !not_equal+ iny lda (atoi_result), y cmp (outer_pointer), y bne !not_equal+ iny lda (atoi_result), y cmp (outer_pointer), y bne !not_equal+ // continue 'outer; jmp !middle_done+ !not_equal: // inner for loop increment // *inner_pointer += 1 * 4 clc lda inner_pointer + 0 adc #4 sta inner_pointer + 0 bcc !+ inc inner_pointer + 1 !: // inner for loop conditional // inner_pointer != outer_pointer lda inner_pointer + 0 cmp outer_pointer + 0 bne !inner- lda inner_pointer + 1 cmp outer_pointer + 1 bne !inner- // for loop increment // *middle_pointer += 1 * 4 clc lda middle_pointer + 0 adc #4 sta middle_pointer + 0 bcc !+ inc middle_pointer + 1 !: // for loop conditional // middle_pointer != outer_pointer lda middle_pointer + 0 cmp outer_pointer + 0 bne !middle_continue+ lda middle_pointer + 1 cmp outer_pointer + 1 bne !middle_continue+ jmp !outer_done+ !middle_continue: jmp !middle- !middle_done: // outer for loop increment // *outer_pointer += 1 * 4 clc lda outer_pointer + 0 adc #4 sta outer_pointer + 0 bcc !+ inc outer_pointer + 1 !: // outer for loop conditional // *outer_pointer != $cfa0 lda outer_pointer + 0 cmp #$a0 bne !outer_continue+ lda outer_pointer + 1 cmp #$bf bne !outer_continue+ jmp * !outer_continue: jmp !outer- !outer_done: // print (part1 = *outer_pointer) ldy #0 lda (outer_pointer), y sta part1 + 0 sta udivmod32_dividend + 0 iny lda (outer_pointer), y sta part1 + 1 sta udivmod32_dividend + 1 iny lda (outer_pointer), y sta part1 + 2 sta udivmod32_dividend + 2 iny lda (outer_pointer), y sta part1 + 3 sta udivmod32_dividend + 3 jsr print_decimal_u32 lda #0 sta lower_pointer + 0 sta upper_pointer + 0 sta sum + 0 sta sum + 1 sta sum + 2 sta sum + 3 lda #$b0 sta lower_pointer + 1 sta upper_pointer + 1 !outer: !upper: // while sum < part1 lda sum + 3 cmp part1 + 3 beq !+ // sum[3] == part1[3] bcc !upper_success+ // sum[3] < part1[3] => sum < part bcs !lower+ // sum[3] >= part1[3] => sum > part !: lda sum + 2 cmp part1 + 2 beq !+ // sum[2] == part1[2] bcc !upper_success+ // sum[2] < part1[2] => sum < part bcs !lower+ // sum[2] >= part1[2] => sum > part !: lda sum + 1 cmp part1 + 1 beq !+ // sum[1] == part1[1] bcc !upper_success+ // sum[1] < part1[1] => sum < part bcs !lower+ // sum[1] >= part1[1] => sum > part !: lda sum + 0 cmp part1 + 0 beq !outer_end+ // sum[0] == part1[0] => sum == part bcs !lower+ // sum[0] >= part1[0] => sum > part !upper_success: // sum += *upper_pointer ldy #0 clc lda sum + 0 adc (upper_pointer), y // (upper_pointer) + 0 sta sum + 0 iny lda sum + 1 adc (upper_pointer), y // (upper_pointer) + 1 sta sum + 1 iny lda sum + 2 adc (upper_pointer), y // (upper_pointer) + 2 sta sum + 2 iny lda sum + 3 adc (upper_pointer), y // (upper_pointer) + 3 sta sum + 3 // upper_pointer += 1 * 4; clc lda upper_pointer + 0 adc #4 sta upper_pointer + 0 bcc !+ inc upper_pointer + 1 !: jmp !upper- !outer_end: // Hidden shortcut to outer_end because the jump was too long jmp !outer_end+ !lower: // while sum > part1 lda sum + 3 cmp part1 + 3 beq !+ // sum[3] == part1[3] bcc !outer- // sum[3] < part[3] => sum < part bcs !lower_success+ // sum[3] >= part[3] => sum > part !: lda sum + 2 cmp part1 + 2 beq !+ // sum[2] == part1[2] bcc !outer- // sum[2] < part[2] => sum < part bcs !lower_success+ // sum[2] >= part[2] => sum > part !: lda sum + 1 cmp part1 + 1 beq !+ // sum[1] == part1[1] bcc !outer- // sum[1] < part[1] => sum < part bcs !lower_success+ // sum[1] >= part[1] => sum > part !: lda sum + 0 cmp part1 + 0 beq !outer_end+ // sum[0] == part1[0] bcs !outer- // sum[0] < part[0] => sum < part !lower_success: // sum -= *lower_pointer ldy #0 sec lda sum + 0 sbc (lower_pointer), y // (lower_pointer) + 0 sta sum + 0 iny lda sum + 1 sbc (lower_pointer), y // (lower_pointer) + 1 sta sum + 1 iny lda sum + 2 sbc (lower_pointer), y // (lower_pointer) + 2 sta sum + 2 iny lda sum + 3 sbc (lower_pointer), y // (lower_pointer) + 3 sta sum + 3 // lower_pointer += 1 * 4; clc lda lower_pointer + 0 adc #4 sta lower_pointer + 0 bcc !+ inc lower_pointer + 1 !: jmp !lower- !lower_end: !outer_end: // Find the minimum and maximum values lda #$ff sta min_value + 0 sta min_value + 1 sta min_value + 2 sta min_value + 3 lda #$00 sta max_value + 0 sta max_value + 1 sta max_value + 2 sta max_value + 3 !loop: ldy #3 lda (lower_pointer), y // lower[i] >> 24 cmp min_value + 3 beq !+ bcs !not_less+ bcc !less+ !: dey lda (lower_pointer), y // lower[i] >> 16 cmp min_value + 2 beq !+ bcs !not_less+ bcc !less+ !: dey lda (lower_pointer), y // lower[i] >> 8 cmp min_value + 1 beq !+ bcs !not_less+ bcc !less+ !: dey lda (lower_pointer), y // lower[i] >> 0 cmp min_value + 0 bcs !not_less+ !less: ldy #0 lda (lower_pointer), y sta min_value + 0 iny lda (lower_pointer), y sta min_value + 1 iny lda (lower_pointer), y sta min_value + 2 iny lda (lower_pointer), y sta min_value + 3 !not_less: ldy #3 lda (lower_pointer), y // lower[i] >> 24 cmp max_value + 3 beq !+ bcc !not_more+ bcs !more+ !: dey lda (lower_pointer), y // lower[i] >> 16 cmp max_value + 2 beq !+ bcc !not_more+ bcs !more+ !: dey lda (lower_pointer), y // lower[i] >> 8 cmp max_value + 1 beq !+ bcc !not_more+ bcs !more+ !: dey lda (lower_pointer), y // lower[i] >> 0 cmp max_value + 0 bcc !not_more+ !more: ldy #0 lda (lower_pointer), y sta max_value + 0 iny lda (lower_pointer), y sta max_value + 1 iny lda (lower_pointer), y sta max_value + 2 iny lda (lower_pointer), y sta max_value + 3 !not_more: clc lda lower_pointer + 0 adc #4 sta lower_pointer + 0 bcc !+ inc lower_pointer + 1 !: // for loop condition // lower_pointer != upper_pointer cmp upper_pointer + 0 bne !+ lda lower_pointer + 1 cmp upper_pointer + 1 beq !end+ !: jmp !loop- !end: clc lda min_value + 0 adc max_value + 0 sta udivmod32_dividend + 0 lda min_value + 1 adc max_value + 1 sta udivmod32_dividend + 1 lda min_value + 2 adc max_value + 2 sta udivmod32_dividend + 2 lda min_value + 3 adc max_value + 3 sta udivmod32_dividend + 3 move_16_imm($03, str_part2) jsr write_string jsr print_decimal_u32 move_16_imm($03, str_done) jsr write_string jmp * rts } !str_title: .text "# Day 09" .byte '\n', '\n' .text "Part 1: " .byte 0