adventofcode2023/08/main.s
2023-12-08 11:10:36 -06:00

208 lines
3.3 KiB
ArmAsm

global _start
[bits 32]
[section .text]
%include "utils.s"
_start:
mov esi, file
; goto end of move string
skip_move:
lodsb
cmp al, 'L'
jge skip_move
; put pairs in memory
xor ebp, ebp ; state
; s0: IDX s1: L s2: R
; get the next thing
get_next_id:
cmp esi, file.over ; input over
jae got_ids
lodsb
cmp al, 'A'
jl get_next_id
cmp al, 'Z'
jg get_next_id
; we have first char
sub al, 'A'
movzx ebx, al ; id
lodsb ; id += next * 26
sub al, 'A'
movzx eax, al
mov ecx, 26
mul ecx
add ebx, eax
lodsb ; id += next * 26^2
sub al, 'A'
movzx eax, al
mov ecx, 26*26
mul ecx
add ebx, eax
; case based on state
cmp ebp, 0
je .idx
cmp ebp, 1
je .left
; right
mov [pairs+edi*8+4], ebx ; right
xor ebp, ebp ; reset state
jmp get_next_id
.left:
mov [pairs+edi*8], ebx ; left
inc ebp ; progress state
jmp get_next_id
.idx:
mov edi, ebx ; curr_id
cmp eax, 0 ; last is A
jne .d
.idx_a:
mov eax, [used_starts]
mov [curr_ids+eax*4], ebx
inc dword [used_starts]
.d:
inc ebp ; progress state
jmp get_next_id
got_ids:
; set what done is
mov ecx, [used_starts]
mov edi, full_cycled
mov al, 1
rep stosb
mov edx, file
; walk move string
find_move_end:
mov esi, edx ; restore
lodsb
cmp al, 'L'
je .left
cmp al, 'R'
je .right
mov edx, file
jmp find_move_end
.right:
mov edx, esi ; save
mov esi, curr_ids
mov edi, curr_ids
mov ecx, [used_starts]
.right_l:
lodsd
mov eax, [pairs+eax*8+4] ; right
stosd
loop .right_l
jmp check_ZZZ
.left:
mov edx, esi ; save
mov esi, curr_ids
mov edi, curr_ids
mov ecx, [used_starts]
.left_l:
lodsd
mov eax, [pairs+eax*8] ; left
stosd
loop .left_l
check_ZZZ:
; find cycles - i'm sure this is an awful way of doing this
inc dword [final_value]
mov esi, curr_ids
xor ecx, ecx
.zzz_l:
lodsd
cmp eax, 16900
jle .zzz_l_cont ; not Z
; check if this Z and string position in cycles
mov edi, ecx
shl edi, 10 ; *1024
add edi, cycles
.check_cycles:
mov ebx, [edi] ; Z
test ebx, ebx
jz .new_cycle
cmp ebx, eax
jne .check_cycles_cont
cmp edx, [edi+4] ; str pos & cycle str pos
jne .check_cycles_cont
; match, increment count
inc dword [edi+8]
mov byte [starts_cycled+ecx], 1
jmp .zzz_l_cont
.check_cycles_cont:
add edi, 16
jmp .check_cycles
.new_cycle:
mov [edi], eax ; Z
mov [edi+4], edx ; str pos
mov dword [edi+8], 1 ; count
mov eax, [final_value]
mov dword [edi+12], eax ; cycle len
.zzz_l_cont:
inc ecx
cmp ecx, [used_starts]
jl .zzz_l
.cont:
; check if we've seen everything cycle
mov ebx, [starts_cycled]
cmp ebx, [full_cycled]
jne find_move_end
mov ebx, [starts_cycled+4]
cmp ebx, [full_cycled+4]
jne find_move_end
; done, print cycles
xor ecx, ecx
print_cycles:
mov esi, ecx
shl esi, 10 ; *1024
add esi, cycles
.l:
lodsd ; Z
mov ebx, eax
test eax, eax
jz .cont
mov eax, ecx ; Start Num
call print_dec
call space
mov eax, ebx
call print_dec
call space
lodsd ; str pos (skip print)
call print_dec
call space
lodsd ; count
call print_dec
call space
lodsd ; cycle len
call print_dec
call newline
jmp .l
.cont:
inc ecx
cmp ecx, [used_starts]
jl print_cycles
.done:
call newline
; lol go use an online calculator for lcm
game_over:
mov eax, [final_value]
call print_dec
jmp exit
[section .data]
final_value: dd 0
used_starts: dd 0
starts_cycled: dq 0
full_cycled: dq 0
file_lim: dd file.over - file
file: incbin "input"
.over:
[section .bss]
curr_ids: resd 8
cycles: resb 1024*16
pairs: resd 131072