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