day 7 part 1

This commit is contained in:
Lucia Ceionia 2023-12-07 01:21:29 -06:00
parent 7e8516a143
commit b71d3da003
5 changed files with 1408 additions and 0 deletions

3
07/Makefile Normal file
View File

@ -0,0 +1,3 @@
all:
nasm -g -felf32 main.s && ld -melf_i386 -g main.o

1000
07/input Normal file

File diff suppressed because it is too large Load Diff

5
07/input_test Normal file
View File

@ -0,0 +1,5 @@
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483

254
07/main_part1.s Normal file
View File

@ -0,0 +1,254 @@
global _start
[bits 32]
[section .text]
%include "utils.s"
; for h in hands
; ; score hands
; tmp := 0
; counts[15] := [0; 15]
; for c in h
; if c > '9'
; if c = 'T' then score := 10
; elif c = 'J' then score := 11
; elif c = 'Q' then score := 12
; elif c = 'K' then score := 13
; elif c = 'A' then score := 14
; else
; score := c - '0'
; end
; tmp := (tmp * 14) + score
; put in counts
; end
; ; check hand type
; has_five := 0
; has_four := 0
; has_three := 0
; has_two := 0
; for n in 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
; ; store tmp in array
; stosd tmp -> 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
get_hand_score:
; do 5 times
; ...
; end
mov ecx, 5
xor ebx, ebx ; char value
.next_char:
lodsb
; if c > '9'
cmp al, '9'
jle .is_num
mov edx, 10
cmp al, 'T'
cmove ebx, edx
mov edx, 11
cmp al, 'J'
cmove ebx, edx
mov edx, 12
cmp al, 'Q'
cmove ebx, edx
mov edx, 13
cmp al, 'K'
cmove ebx, edx
mov edx, 14
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:
; tmp *= 14
; tmp += score
mov eax, ebp
mov edx, 14
mul edx
add eax, ebx
mov ebp, eax
; put in counts
inc byte [counts+ebx]
loop .next_char
; 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 counts
mov ecx, 15
push esi ; save line
mov esi, 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:
; store tmp & bid in array
mov eax, ebp
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
counts: times 15 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

146
07/utils.s Normal file
View File

@ -0,0 +1,146 @@
; call # val val2
; int $0x80 eax eax edx -
;
; arg1 arg2 arg3 arg4 arg5 arg6 arg7
; ebx ecx edx esi edi ebp -
exit:
mov eax, 1 ; exit
int 0x80
; filename in EBX
; return handle in EBX
; read only
open_file:
push eax
push ecx
mov eax, 5 ; open
xor ecx, ecx ; read only
int 0x80
mov ebx, eax
pop ecx
pop eax
ret
; file handle in EBX
; buffer in ECX
; count of bytes to read in EDX
; return bytes actually read in EAX
; exits on error
read_file:
mov eax, 3 ; read
int 0x80
test eax, eax
js .err
ret
.err:
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, .err_str
mov edx, 21
int 0x80
jmp exit
.err_str: db `Could not read file.\n`
; string input in ESI
; value in EAX
; CF set if none, clear if some
; ESI set past checked area
dec_parse:
push ebx
push edx
push edi
xor eax, eax
xor edi, edi
mov ebx, 10 ; base
lodsb
sub al, '0'
js .no_input
cmp al, 9
jle .got_char
.no_input:
stc ; set CF
jmp .done
.loop:
xor eax,eax
lodsb
sub al, '0'
js .dec_done
cmp al, 9
jg .dec_done
.got_char:
xchg edi,eax
mul ebx
add edi,eax
jmp .loop
.dec_done:
clc ; clear CF
.done:
mov eax,edi
pop edi
pop edx
pop ebx
ret
; modifies no regs
newline:
pushad
push 10
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, esp ; string
mov edx, 1 ; length
int 0x80
add esp, 4
popad
ret
; modifies no regs
space:
pushad
push 9
mov eax, 4 ; write
mov ebx, 1 ; stdout
mov ecx, esp ; string
mov edx, 1 ; length
int 0x80
add esp, 4
popad
ret
; input in EAX, all regs unmodified
print_dec:
pushad ; save regs
; max 4294967296 is 10 chars
; round to nearest 32-bit boundary
sub esp, 12
; string in ECX, length in EDX
lea ecx, [esp+11] ; last possible byte
; check for 0
test eax, eax
jz .zero
mov ebx, 10 ; base 10
xor esi, esi ; counter
.div_shit:
xor edx, edx
; divide
div ebx
dec ecx ; next char
inc esi
; store
add dl, '0'
mov byte [ecx], dl
; check if done
test eax, eax
jnz .div_shit ; continue
mov edx, esi ; counter in edx
jmp .write
.zero:
mov byte [ecx], '0'
mov edx, 1 ; length
.write:
mov eax, 4 ; write
mov ebx, 1 ; stdout
int 0x80
add esp, 12 ; restore stack
popad ; restore regs
ret