diff options
| author | hachem <im@hachem.wtf> | 2026-09-06 04:12:25 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-06 04:12:25 +0200 |
| commit | 054d372a716bca4f628674e524e3d027f6824019 (patch) | |
| tree | f1b8a86430476b4aed8173857bdab0f960e5fdb1 /2025/day3.asm | |
| parent | 78c4d3d06d8e863cfe2489281ccfe206544cbd7f (diff) | |
refactor: clean up repository layout
Diffstat (limited to '2025/day3.asm')
| -rw-r--r-- | 2025/day3.asm | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/2025/day3.asm b/2025/day3.asm new file mode 100644 index 0000000..8330755 --- /dev/null +++ b/2025/day3.asm @@ -0,0 +1,234 @@ +; Advent of Code 2025 - Day 3 + +bits 64 +default rel + +global _start + +%include "utils/io.asm" + +section .data + input_path db "input/day3.txt", 0 + + label1 db "Part 1: ", 0 + label2 db "Part 2: ", 0 + +section .bss + buffer resb 4096 + line_buffer resb 65536 + line_len resd 1 + + sum1 resq 1 + sum2 resq 1 + + work_digits resb 64 ; stack for greedy subsequence + +section .text + +_start: + mov rax, SYS_OPEN + mov rdi, input_path + mov rsi, O_RDONLY + xor rdx, rdx + syscall + + mov r12, rax ; fd + mov dword [line_len], 0 + +read_loop: + mov rax, SYS_READ + mov rdi, r12 + mov rsi, buffer + mov rdx, 4096 + syscall + + cmp rax, 0 + jle eof + + mov rdi, buffer + mov rbp, rax + +scan_chunk: + cmp rbp, 0 + je read_loop + + mov al, [rdi] + + cmp al, 13 + je skip_cr + + cmp al, 10 + je end_line + + mov edx, [line_len] + cmp edx, 65535 + jae skip_store + mov [line_buffer+rdx], al + inc edx + mov [line_len], edx + +skip_store: + inc rdi + dec rbp + jmp scan_chunk + +skip_cr: + inc rdi + dec rbp + jmp scan_chunk + +end_line: + mov edx, [line_len] + mov byte [line_buffer+edx], 0 + + cmp edx, 0 + je clear_line + + push rdi + mov rsi, line_buffer + call handle_line + pop rdi + +clear_line: + mov dword [line_len], 0 + inc rdi + dec rbp + jmp scan_chunk + +eof: + ; possible last partial line + mov edx, [line_len] + cmp edx, 0 + jle print_results + + mov byte [line_buffer+edx], 0 + mov rsi, line_buffer + call handle_line + +print_results: + mov rcx, label1 + call print_string + mov rax, [sum1] + call print_int64 + call print_newline + + mov rcx, label2 + call print_string + mov rax, [sum2] + call print_int64 + call print_newline + + mov rax, SYS_CLOSE + mov rdi, r12 + syscall + + mov rax, SYS_EXIT + xor rdi, rdi + syscall + +handle_line: + mov rdi, rsi + xor ecx, ecx ; ECX = 0 +.length_loop: + mov al, [rdi+rcx] + cmp al, 0 + je .length_done + inc ecx + jmp .length_loop +.length_done: + mov r15d, ecx ; r15d = n + + ; part 1: k = 2 + mov ecx, r15d ; ECX = n + mov edi, 2 ; K = 2 + call get_max_for_k ; RAX = best 2-digit value + add qword [sum1], rax + + ; part 2: k = 12, only if n >= 12 + cmp r15d, 12 + jl .skip_part2 + + mov ecx, r15d + mov edi, 12 + call get_max_for_k ; RAX = best 12-digit value + add qword [sum2], rax + +.skip_part2: + ret + +; Greedy lexicographically largest subsequence of length K +; +; Input: +; RSI -> digits string +; ECX = n (length) +; EDI = k +; Output: +; RAX = numeric value of chosen k digits +; Clobbers: R8..R11, EAX, EDX +get_max_for_k: + ; drops_remaining = n - k + mov eax, ecx + sub eax, edi + mov r8d, eax ; r8d = drops + + xor r9d, r9d ; r9d = stack_size + xor r10d, r10d ; r10d = i + +.loop: + cmp r10d, ecx + jge .after_input + + ; current digit in AL + mov r11, r10 + mov al, [rsi + r11] + +.pop: + cmp r9d, 0 + jle .push + cmp r8d, 0 + jle .push + + mov edx, r9d + dec edx + mov r11d, edx + mov bl, [work_digits + r11] + + cmp bl, al + jge .push + + dec r9d + dec r8d + jmp .pop +.push: + mov r11d, r9d + mov [work_digits + r11], al + inc r9d + inc r10d + jmp .loop + +.after_input: + ; trim if stack_size > k +.trim: + cmp r9d, edi + jle .convert + dec r9d + jmp .trim +.convert: + xor rax, rax + xor r11d, r11d +.convert_loop: + cmp r11d, edi + jge .done + + mov rdx, r11 + mov dl, [work_digits + rdx] + sub dl, '0' + movzx rdx, dl + + imul rax, rax, 10 + add rax, rdx + + inc r11d + jmp .convert_loop +.done: + ret |
