hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/aoc-2025/day5.asm
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-06 04:12:25 +0200
committerhachem <im@hachem.wtf>2026-09-06 04:12:25 +0200
commit054d372a716bca4f628674e524e3d027f6824019 (patch)
treef1b8a86430476b4aed8173857bdab0f960e5fdb1 /aoc-2025/day5.asm
parent78c4d3d06d8e863cfe2489281ccfe206544cbd7f (diff)
refactor: clean up repository layout
Diffstat (limited to 'aoc-2025/day5.asm')
-rw-r--r--aoc-2025/day5.asm225
1 files changed, 0 insertions, 225 deletions
diff --git a/aoc-2025/day5.asm b/aoc-2025/day5.asm
deleted file mode 100644
index 4718343..0000000
--- a/aoc-2025/day5.asm
+++ /dev/null
@@ -1,225 +0,0 @@
-; Advent of Code 2025 - Day 5
-
-bits 64
-default rel
-
-global _start
-
-%include "utils/io.asm"
-%include "utils/parse.asm"
-
-%define RAW_SIZE 1048576 ; 1 MiB scratch for the raw file
-%define MAX_RANGES 8192 ; plenty for the ~177 input ranges
-
-section .data
- input_path db "input/day5.txt", 0
-
- label1 db "Part 1: ", 0
- label2 db "Part 2: ", 0
-
-section .bss
- raw resb RAW_SIZE
- starts resq MAX_RANGES ; range/merged-interval starts
- ends resq MAX_RANGES ; range/merged-interval ends
-
- raw_len resq 1
- n_ranges resq 1 ; ranges parsed in section 1
- n_merged resq 1 ; disjoint intervals after merge
- phase resq 1 ; 0 = ranges, 1 = available IDs
-
- part1 resq 1
- part2 resq 1
-
-section .text
-
-_start:
- mov rdi, input_path
- lea rsi, [raw]
- mov rdx, RAW_SIZE
- call read_file
- mov [raw_len], rax
-
- ; RSI = cursor, R14 = end pointer (both preserved across helper calls)
- lea rsi, [raw]
- mov rax, [raw_len]
- lea r14, [raw + rax]
- mov qword [phase], 0
-
-scan_line:
- cmp rsi, r14
- jae scan_done
- mov al, [rsi]
- cmp al, 10 ; LF -> blank line
- je got_blank
- cmp al, 13 ; CR -> blank line
- je got_blank
-
- cmp qword [phase], 0
- jne do_avail
-
- call parse_u64 ; RAX = start
- mov rcx, [n_ranges]
- mov [starts + rcx*8], rax
- inc rsi ; skip '-'
- call parse_u64 ; RAX = end
- mov rcx, [n_ranges]
- mov [ends + rcx*8], rax
- inc qword [n_ranges]
- jmp skip_eol
-
-do_avail:
- call parse_u64
- mov rdi, rax
- call is_fresh ; RAX = 1 if fresh
- test rax, rax
- jz skip_eol
- inc qword [part1]
- jmp skip_eol
-
-got_blank:
- ; the blank line separates the two sections
- cmp qword [phase], 0
- jne skip_eol
- call finalize_ranges ; sort + merge, compute part2
- mov qword [phase], 1
- ; fall through
-
-skip_eol:
- cmp rsi, r14
- jae scan_done
- mov al, [rsi]
- inc rsi
- cmp al, 10 ; consume through the LF
- jne skip_eol
- jmp scan_line
-
-scan_done:
- ; safety: if there was no blank line, still finalize the ranges
- cmp qword [phase], 0
- jne print_results
- call finalize_ranges
-
-print_results:
- mov rcx, label1
- call print_string
- mov rax, [part1]
- call print_int64
- call print_newline
-
- mov rcx, label2
- call print_string
- mov rax, [part2]
- call print_int64
- call print_newline
-
- mov rax, SYS_EXIT
- xor rdi, rdi
- syscall
-
-; is_fresh: test membership of an ID in the merged intervals.
-; Input: RDI = id
-; Output: RAX = 1 if the id lies in any interval, else 0
-; Intervals are sorted ascending and disjoint, so we can stop early.
-; Clobbers: RAX, RCX
-is_fresh:
- xor rcx, rcx
-.loop:
- cmp rcx, [n_merged]
- jge .no
- mov rax, [starts + rcx*8]
- cmp rdi, rax
- jl .no ; id below this start -> below all later ones
- mov rax, [ends + rcx*8]
- cmp rdi, rax
- jle .yes ; start <= id <= end
- inc rcx
- jmp .loop
-.no:
- xor eax, eax
- ret
-.yes:
- mov eax, 1
- ret
-
-; finalize_ranges: insertion-sort the ranges by start, merge overlapping /
-; touching ones in place, store the disjoint intervals back into starts/ends,
-; set n_merged, and accumulate their total size into part2.
-; Clobbers: RAX, RCX, RDX, R8, R9, R10, R11, R12, R13
-finalize_ranges:
- mov r8, 1 ; i
-.sort_i:
- cmp r8, [n_ranges]
- jge .sorted
- mov r10, [starts + r8*8] ; key_s
- mov r11, [ends + r8*8] ; key_e
- mov r9, r8
- dec r9 ; j = i - 1
-.sort_j:
- cmp r9, 0
- jl .sort_place
- mov rax, [starts + r9*8]
- cmp rax, r10
- jle .sort_place ; starts[j] <= key -> in place
- mov rdx, r9
- inc rdx ; j + 1
- mov [starts + rdx*8], rax ; shift start
- mov rcx, [ends + r9*8]
- mov [ends + rdx*8], rcx ; shift end
- dec r9
- jmp .sort_j
-.sort_place:
- mov rdx, r9
- inc rdx
- mov [starts + rdx*8], r10
- mov [ends + rdx*8], r11
- inc r8
- jmp .sort_i
-.sorted:
-
- cmp qword [n_ranges], 0
- je .empty
-
- mov r10, [starts] ; cur_lo
- mov r11, [ends] ; cur_hi
- mov r8, 1 ; i
- xor r12, r12 ; part2 accumulator
- xor r13, r13 ; write index
-.merge_loop:
- cmp r8, [n_ranges]
- jge .flush
- mov rax, [starts + r8*8] ; s
- mov rcx, [ends + r8*8] ; e
- cmp rax, r11
- jg .gap ; s > cur_hi -> disjoint
- cmp rcx, r11 ; overlap: cur_hi = max(cur_hi, e)
- jle .no_extend
- mov r11, rcx
-.no_extend:
- inc r8
- jmp .merge_loop
-.gap:
- call .emit
- mov r10, rax ; begin new interval
- mov r11, rcx
- inc r8
- jmp .merge_loop
-.flush:
- call .emit
- mov [n_merged], r13
- mov [part2], r12
- ret
-.empty:
- mov qword [n_merged], 0
- mov qword [part2], 0
- ret
-
-; local helper: emit [r10, r11] as merged interval r13, add its size to r12
-.emit:
- mov [starts + r13*8], r10
- mov [ends + r13*8], r11
- inc r13
- mov rdx, r11
- sub rdx, r10
- inc rdx ; end - start + 1
- add r12, rdx
- ret