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