From 43d12dae956e8419269f5d1da19a3e6c51f1a989 Mon Sep 17 00:00:00 2001 From: Lucia Ceionia Date: Thu, 7 Dec 2023 02:48:10 -0600 Subject: [PATCH] day 7 part 2 --- 07/main.s | 376 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 376 insertions(+) create mode 100644 07/main.s diff --git a/07/main.s b/07/main.s new file mode 100644 index 0000000..035d6e0 --- /dev/null +++ b/07/main.s @@ -0,0 +1,376 @@ +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