208 lines
3.3 KiB
ArmAsm
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
|