adventofcode2023/07/main.s

377 lines
6.7 KiB
ArmAsm
Raw Normal View History

2023-12-07 02:48:10 -06:00
global _start
[bits 32]
[section .text]
%include "utils.s"
; for h in hands
; ; score hands
; tmp := 0
; counts[15] := [0; 15]
; joker_values := [0; 5]
; for c in h
; if c > '9'
; if c = 'T' then value := 10
; elif c = 'J' then
; value := 1
; joker_values[char_idx] := 1
; end
; elif c = 'Q' then value := 11
; elif c = 'K' then value := 12
; elif c = 'A' then value := 13
; else
; value := c - '0'
; end
; tmp := (tmp * 14) + value
; put in counts
; end
; ; joker bs
; orig_val := tmp
; best_score := orig_val
; loop
; fake_counts := counts
; tmp := orig_val
; for j in joker_values where j != 0
; fake_counts[j] += 1
; end
;
; ; check hand type
; has_five := 0
; has_four := 0
; has_three := 0
; has_two := 0
; for n in fake_counts
; if n = 5 then inc has_five
; if n = 4 then inc has_four
; if n = 3 then inc has_three
; if n = 2 then inc has_two
; end
; if has_five then tmp := tmp + 60,000,000
; elif has_four then tmp := tmp + 50,000,000
; elif has_three and has_two then tmp := tmp + 40,000,000
; elif has_three then tmp := tmp + 30,000,000
; elif has_two = 2 then tmp := tmp + 20,000,000
; elif has_two = 1 then tmp := tmp + 10,000,000
; if tmp > best_score then best_score := tmp
;
; last_joker_carried := 1
; i := 0
; loop
; if joker_values[i] + 1 = 14 then
; joker_values[i] = 2
; else
; joker_values[i] += 1
; last_joker_carried := 0
; end
; .cont:
; inc i
; if i = 5 then break
; if !last_joker_carried then break
; end
; if last_joker_carried then break
; end
; ; store in array
; stosd best_score -> hand_array
; stosd bid -> hand_array
; end
;
; bubble sort hand_array
;
; calc total
; rank := 1
; for (_, bid) in hand_array
; final_value += rank * bid
; rank += 1
; end
;
; done
_start:
mov esi, file
mov edi, hand_array
; for l in lines
; ...
; end
for_in_lines:
; check for end
cmp esi, file.over
jae for_in_lines_end
; score hand
; tmp := 0
xor ebp, ebp ; tmp
; counts[15] := [0; 15]
push edi
mov edi, counts
mov ecx, 15
xor eax, eax
rep stosb
pop edi
; zero joker_values
mov dword [joker_values], 0
mov dword [joker_values+4], 0
get_hand_score:
; do 5 times
; ...
; end
mov ecx, 5
xor ebx, ebx ; char value
push edi ; save edi
xor edi, edi ; idx
.next_char:
lodsb
; if c > '9'
cmp al, '9'
jle .is_num
mov edx, 10
cmp al, 'T'
cmove ebx, edx
cmp al, 'J'
jne .not_joker
mov ebx, 1
mov byte [joker_values+edi], 1
jmp .add_to_tmp_skip_counts
.not_joker:
mov edx, 11
cmp al, 'Q'
cmove ebx, edx
mov edx, 12
cmp al, 'K'
cmove ebx, edx
mov edx, 13
cmp al, 'A'
cmove ebx, edx
jmp .add_to_tmp
.is_num:
; else val := c - '0'
sub al, '0'
movzx ebx, al
; end
.add_to_tmp:
; put in counts
inc byte [counts+ebx]
.add_to_tmp_skip_counts:
; tmp *= 14
; tmp += score
mov eax, ebp
mov edx, 14
mul edx
add eax, ebx
mov ebp, eax
inc edi ; idx
loop .next_char
pop edi ; restore edi
; joker bs
joker_bs:
push ebp ; best_score (esp + 4)
push ebp ; orig_val (esp)
; loop .. end
joker_loop:
; fake_counts := counts
; tmp := orig_val
mov eax, [counts+0]
mov [fake_counts+0], eax
mov eax, [counts+4]
mov [fake_counts+4], eax
mov eax, [counts+8]
mov [fake_counts+8], eax
mov eax, [counts+12]
mov [fake_counts+12], eax
mov ebp, [esp] ; tmp := orig_val
; for j in joker_values where j != 0
; fake_counts[j] += 1
; end
push esi
mov ecx, 5
mov esi, joker_values
xor eax, eax
add_fake_counts:
lodsb
inc byte [fake_counts+eax]
.cont:
loop add_fake_counts
mov byte [fake_counts], 0 ; idx 0 is always 0
pop esi
; check hand type
mov byte [has_five], 0
mov byte [has_four], 0
mov byte [has_three], 0
mov byte [has_two], 0
; for n in fake_counts
mov ecx, 15
push esi ; save line
mov esi, fake_counts
check_counts:
lodsb
cmp al, 5
jne .check_4
inc byte [has_five]
.check_4:
cmp al, 4
jne .check_3
inc byte [has_four]
.check_3:
cmp al, 3
jne .check_2
inc byte [has_three]
.check_2:
cmp al, 2
jne .check_cont
inc byte [has_two]
.check_cont:
loop check_counts
; end
pop esi ; restore line
cmp byte [has_five], 0
je .maybe_four
add ebp, 60000000
jmp .save
.maybe_four:
cmp byte [has_four], 0
je .maybe_three
add ebp, 50000000
jmp .save
.maybe_three:
cmp byte [has_three], 0
je .maybe_twos
add ebp, 30000000
.maybe_twos:
mov cl, byte [has_two]
cmp cl, 0
je .save
mov eax, 10000000/2
shl eax, cl
add ebp, eax
.save:
; if tmp > best_score then best_score := tmp
cmp ebp, [esp+4] ; best_score
jbe .not_better
mov [esp+4], ebp
.not_better:
mov edx, 1 ; last_joker_carried := 1
xor ecx, ecx ; i := 0
; loop..end
increment_jokers:
; if joker_values[i] + 1 = 14 then
; joker_values[i] = 2
; else
; joker_values[i] += 1
; last_joker_carried := 0
; end
cmp byte [joker_values+ecx], 0
je .cont
cmp byte [joker_values+ecx], 13
jne .else
mov byte [joker_values+ecx], 2
jmp .cont
.else:
inc byte [joker_values+ecx]
xor edx, edx
.cont:
inc ecx ; i += 1
; if i = 5 then break
; if !last_joker_carried then break
cmp ecx, 5
je increment_jokers_end
test edx, edx
jz increment_jokers_end
jmp increment_jokers
increment_jokers_end:
; if last_joker_carried then break
test edx, edx
jnz joker_bs_end
joker_loop_end:
jmp joker_loop
joker_bs_end:
pop eax ; orig_val (discard)
pop eax ; best_score
real_save:
; store best_score & bid in array
stosd
inc esi ; skip space
call dec_parse ; bid
stosd
for_in_lines_cont:
jmp for_in_lines
for_in_lines_end:
; bubble sort hand_array
bubble_sort:
; get length (array is null terminated)
mov esi, hand_array
xor eax, eax
get_len:
cmp dword [esi+eax*8], 0
je .done
inc eax
jmp get_len
.done:
mov ebp, eax ; n
do_sort:
xor edx, edx ; newn
mov ecx, 1 ; i
.inner:
mov eax, [esi+ecx*8-8] ; A[i-1]
cmp eax, [esi+ecx*8] ; A[i]
jbe .inner_cont
; swap elements
xchg eax, [esi+ecx*8]
mov [esi+ecx*8-8], eax
mov eax, [esi+ecx*8-4] ; A[i-1] bid
xchg eax, [esi+ecx*8+4] ; A[i] bid
mov [esi+ecx*8-4], eax
mov edx, ecx ; newn
.inner_cont:
inc ecx
cmp ecx, ebp
jb .inner
mov ebp, edx ; n := newn
cmp ebp, 1
ja do_sort ; until n <= 1
done_sort:
; calc total
; rank := 1
mov ebx, 1
mov esi, hand_array
calc_total:
lodsd ; _
lodsd ; bid
test eax, eax
jz calc_total_done
mul ebx
add [final_value], eax
inc ebx
jmp calc_total
calc_total_done:
game_over:
mov eax, [final_value]
call print_dec
jmp exit
[section .data]
final_value: dd 0
joker_values: times 8 db 0 ; we only use 5 but this makes zeroing easier
counts: times 16 db 0 ; only use 14 or 13 but whatever
fake_counts: times 16 db 0
has_five: db 0
has_four: db 0
has_three: db 0
has_two: db 0
file_lim: dd file.over - file
file: incbin "input"
.over:
[section .bss]
hand_array: resd 4096