From 82e76592b5993889a93aa00397333e7479bce2ed Mon Sep 17 00:00:00 2001 From: hachem Date: Sat, 6 Dec 2025 09:55:15 +0100 Subject: [complete]: day 2 --- src/Day2.asm | 407 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 395 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/Day2.asm b/src/Day2.asm index 7e154da..dfbfb38 100644 --- a/src/Day2.asm +++ b/src/Day2.asm @@ -1,27 +1,410 @@ -; Advent of Code 2025 - Day 2 +; Advent of Code 2025 – Day 2 bits 64 default rel global _start -%define SYS_EXIT 60 -%define SYS_WRITE 1 +%define SYS_EXIT 60 +%define SYS_READ 0 +%define SYS_WRITE 1 +%define SYS_OPEN 2 +%define SYS_CLOSE 3 -%define STDOUT 1 +%define O_RDONLY 0 +%define STDOUT 1 section .data - message db "Hello Day 2!", 0xA - length equ $-message + inputPath db "input/day2.txt", 0 + newline db 10 + + label1 db "Part 1: ", 0 + label2 db "Part 2: ", 0 + +section .bss + buffer resb 4096 + lineBuffer resb 65536 + lineLen resd 1 + + sum1 resq 1 + sum2 resq 1 + + numberBuffer resb 32 ; for printing and NumberToString section .text + _start: - mov rax, SYS_WRITE - mov rdi, STDOUT - mov rsi, message - mov rdx, length + mov rax, SYS_OPEN + mov rdi, inputPath + mov rsi, O_RDONLY + xor rdx, rdx + syscall + + mov r12, rax ; file descriptor + mov dword [lineLen], 0 + +ReadLoop: + 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 + +ScanChunk: + cmp rbp, 0 + je ReadLoop + + mov al, [rdi] + + cmp al, 13 + je SkipCR + + cmp al, 10 + je EndLine + + mov edx, [lineLen] + cmp edx, 65535 + jae SkipStore + mov [lineBuffer+rdx], al + inc edx + mov [lineLen], edx + +SkipStore: + inc rdi + dec rbp + jmp ScanChunk + +SkipCR: + inc rdi + dec rbp + jmp ScanChunk + +EndLine: + mov edx, [lineLen] + mov byte [lineBuffer+rdx], 0 + + cmp edx, 0 + je ClearLine + + push rdi + mov rsi, lineBuffer + call HandleLine + pop rdi + +ClearLine: + mov dword [lineLen], 0 + inc rdi + dec rbp + jmp ScanChunk + +EOF: + ; process final partial line if needed + mov edx, [lineLen] + cmp edx, 0 + jle PrintResults + + mov byte [lineBuffer+rdx], 0 + mov rsi, lineBuffer + call HandleLine + +PrintResults: + mov rcx, label1 + call PrintString + mov rax, [sum1] + call PrintInt64 + call Newline + + mov rcx, label2 + call PrintString + mov rax, [sum2] + call PrintInt64 + call Newline + + mov rax, SYS_CLOSE + mov rdi, r12 + syscall + + mov rax, SYS_EXIT + xor rdi, rdi + syscall + +; parse "A-B,C-D,..."l, RSI = pointer to line +; uses r13 = current ID, r14 = end of range +HandleLine: +NextRange: + ; parse start + call ParseInt64 + mov r13, rax + + cmp byte [rsi], '-' + jne DoneLine + inc rsi + + ; parse end + call ParseInt64 + mov r14, rax + +RangeLoop: + cmp r13, r14 + jg AfterRange + + ; Save RSI (line pointer) across the checks, + ; because NumberToString / CheckInvalid* use RSI + push rsi + + ; Part 1: exact AA + mov rax, r13 + call CheckInvalid1 + test rax, rax + jz .skipP1 + add qword [sum1], r13 +.skipP1: + ; Part 2: any repeating block >= 2 + mov rax, r13 + call CheckInvalid2 + test rax, rax + jz .skipP2 + add qword [sum2], r13 +.skipP2: + pop rsi ; restore line pointer + + inc r13 + jmp RangeLoop + +AfterRange: + cmp byte [rsi], ',' + jne DoneLine + inc rsi + jmp NextRange + +DoneLine: + ret + +; RSI points at decimal digits; stops on first non-digit +ParseInt64: + xor rax, rax +.parse: + mov dl, [rsi] + cmp dl, '0' + jl .done + cmp dl, '9' + jg .done + + sub dl, '0' + movzx rdx, dl + imul rax, rax, 10 + add rax, rdx + + inc rsi + jmp .parse +.done: + ret + +; NumberToString: convert RAX to decimal ASCII, MSB-first +; Output: +; RSI = pointer to first digit +; ECX = length +NumberToString: + mov rdi, numberBuffer+31 + mov byte [rdi], 0 ; terminator (for convenience) + dec rdi + + cmp rax, 0 + jne .conv + + ; handle zero + mov byte [rdi], '0' + mov rsi, rdi + mov ecx, 1 + ret + +.conv: + mov rbx, 10 +.nextDigit: + xor rdx, rdx + div rbx ; RAX = quotient, RDX = remainder + add dl, '0' + mov [rdi], dl + dec rdi + test rax, rax + jnz .nextDigit + + inc rdi ; now RDI points to first digit + mov rsi, rdi + mov rdx, numberBuffer+31 + sub rdx, rsi ; RDX = length + mov ecx, edx + ret + +; CheckInvalid1: "AA" pattern +; RAX = number +; Returns RAX = 1 if digits == A A, else 0 +CheckInvalid1: + push rbx + push rdx + + call NumberToString ; RSI=string, ECX=len + mov eax, ecx ; EAX = len + + cmp eax, 2 + jl .no1 + + test eax, 1 + jnz .no1 ; odd length => cannot be AA + + shr eax, 1 ; half = len/2 + mov r8d, eax ; half + xor r9d, r9d ; i = 0 + +.loop1: + cmp r9d, r8d + jge .yes1 + + ; s[i] + mov rdx, r9 + movzx eax, byte [rsi + rdx] + + ; s[i+half] + mov rdx, r9 + add rdx, r8 + movzx ebx, byte [rsi + rdx] + + cmp eax, ebx + jne .no1 + + inc r9d + jmp .loop1 + +.yes1: + mov rax, 1 + jmp .ret1 + +.no1: + xor rax, rax + +.ret1: + pop rdx + pop rbx + ret + +; CheckInvalid2: any repeating block >= 2 +; RAX = number +; Returns RAX = 1 if string is some A repeated k>=2 times +CheckInvalid2: + push rbx + push rdx + + call NumberToString ; RSI=string, ECX=len + mov r11d, ecx ; n = length + + cmp r11d, 2 + jb .no2 + + mov r8d, 1 ; m = 1 (candidate period) +.outer: + cmp r8d, r11d + jge .no2 + + ; if n % m != 0 => cannot tile + mov eax, r11d + xor edx, edx + div r8d ; EAX=q, EDX=r + test edx, edx + jnz .next_m + + mov r9d, r11d + sub r9d, r8d ; limit = n - m + xor r10d, r10d ; i = 0 +.inner: + cmp r10d, r9d + jge .yes2 ; all positions checked + + ; s[i] + mov rdx, r10 + movzx eax, byte [rsi + rdx] + + ; s[i+m] + mov rdx, r10 + add rdx, r8 + movzx ebx, byte [rsi + rdx] + + cmp eax, ebx + jne .next_m + + inc r10d + jmp .inner +.yes2: + mov rax, 1 + jmp .ret2 +.next_m: + inc r8d + jmp .outer +.no2: + xor rax, rax +.ret2: + pop rdx + pop rbx + ret + +Newline: + mov rax, SYS_WRITE + mov rdi, STDOUT + mov rsi, newline + mov rdx, 1 + syscall + ret + +PrintInt64: + mov rdi, numberBuffer+31 + mov byte [rdi], 0 + dec rdi + + cmp rax, 0 + jne .conv + + mov byte [rdi], '0' + jmp .done +.conv: + mov rbx, 10 +.next: + xor rdx, rdx + div rbx + add dl, '0' + mov [rdi], dl + dec rdi + test rax, rax + jnz .next + + inc rdi +.done: + mov rax, SYS_WRITE + mov rsi, rdi + mov rdi, STDOUT + mov rdx, numberBuffer+31 + sub rdx, rsi syscall + ret - mov rax, SYS_EXIT - xor rdi, rdi +PrintString: + push rcx + push rdx + mov rdx, 0 +.length: + cmp byte [rcx+rdx], 0 + je .submit + inc rdx + jmp .length +.submit: + mov rax, SYS_WRITE + mov rdi, STDOUT + mov rsi, rcx syscall + pop rdx + pop rcx + ret -- cgit v1.3