1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
|
; Advent of Code 2025 - Day 9
bits 64
default rel
global _start
%include "utils/io.asm"
%include "utils/parse.asm"
%define RAW_SIZE 262144
%define MAXN 512
%define MAXC 1024
%define MAXR 1024
%define MAXP ((MAXC + 1) * (MAXR + 1))
section .data
input_path db "input/day9.txt", 0
label1 db "Part 1: ", 0
label2 db "Part 2: ", 0
section .bss
raw resb RAW_SIZE
vx resq MAXN
vy resq MAXN
xs resq MAXN
ys resq MAXN
xs_to_col resd MAXN
ys_to_row resd MAXN
col_lo resq MAXC
row_lo resq MAXR
thincol resd MAXN
thinrow resd MAXN
vex resq MAXN ; vertical edges: x, ylo, yhi
veylo resq MAXN
veyhi resq MAXN
hey resq MAXN ; horizontal edges: y, xlo, xhi
hexlo resq MAXN
hexhi resq MAXN
pref resd MAXP ; 2D prefix sum of unfilled cells
raw_len resq 1
n_v resq 1
xn resq 1
yn resq 1
c_cnt resq 1
r_cnt resq 1
cp1 resq 1
ve_cnt resq 1
he_cnt resq 1
best1 resq 1
best2 resq 1
section .text
_start:
mov rdi, input_path
lea rsi, [raw]
mov rdx, RAW_SIZE
call read_file
mov [raw_len], rax
; parse "X,Y" vertices in order
lea rsi, [raw]
mov rax, [raw_len]
lea r14, [raw + rax]
xor r12, r12
parse_line:
cmp rsi, r14
jae parse_done
mov al, [rsi]
cmp al, 10
je parse_skipnl
cmp al, 13
je parse_skipnl
call parse_u64
mov [vx + r12*8], rax
inc rsi
call parse_u64
mov [vy + r12*8], rax
inc r12
parse_eol:
cmp rsi, r14
jae parse_done
mov al, [rsi]
inc rsi
cmp al, 10
jne parse_eol
jmp parse_line
parse_skipnl:
inc rsi
jmp parse_line
parse_done:
mov [n_v], r12
; xs = sorted, deduped x coordinates
xor rcx, rcx
copy_xs:
cmp rcx, [n_v]
jge copy_xs_done
mov rax, [vx + rcx*8]
mov [xs + rcx*8], rax
inc rcx
jmp copy_xs
copy_xs_done:
lea rdi, [xs]
mov rsi, [n_v]
call sort_q
lea rdi, [xs]
mov rsi, [n_v]
call dedup_q
mov [xn], rax
; ys = sorted, deduped y coordinates
xor rcx, rcx
copy_ys:
cmp rcx, [n_v]
jge copy_ys_done
mov rax, [vy + rcx*8]
mov [ys + rcx*8], rax
inc rcx
jmp copy_ys
copy_ys_done:
lea rdi, [ys]
mov rsi, [n_v]
call sort_q
lea rdi, [ys]
mov rsi, [n_v]
call dedup_q
mov [yn], rax
; refined columns: thin at each xs, thick strip between
xor rcx, rcx ; i
xor r12, r12 ; column count
build_cols:
cmp rcx, [xn]
jge build_cols_done
mov [xs_to_col + rcx*4], r12d
mov rax, [xs + rcx*8]
mov [col_lo + r12*8], rax
inc r12
mov rdx, rcx
inc rdx
cmp rdx, [xn]
jge build_cols_next
mov r8, [xs + rdx*8]
mov rax, [xs + rcx*8]
sub r8, rax
cmp r8, 1
jle build_cols_next
inc rax
mov [col_lo + r12*8], rax
inc r12
build_cols_next:
inc rcx
jmp build_cols
build_cols_done:
mov [c_cnt], r12
inc r12
mov [cp1], r12
; refined rows: thin at each ys, thick strip between
xor rcx, rcx
xor r12, r12
build_rows:
cmp rcx, [yn]
jge build_rows_done
mov [ys_to_row + rcx*4], r12d
mov rax, [ys + rcx*8]
mov [row_lo + r12*8], rax
inc r12
mov rdx, rcx
inc rdx
cmp rdx, [yn]
jge build_rows_next
mov r8, [ys + rdx*8]
mov rax, [ys + rcx*8]
sub r8, rax
cmp r8, 1
jle build_rows_next
inc rax
mov [row_lo + r12*8], rax
inc r12
build_rows_next:
inc rcx
jmp build_rows
build_rows_done:
mov [r_cnt], r12
; per-vertex refined thin column / row index
xor r8, r8
map_v:
cmp r8, [n_v]
jge map_v_done
mov r13, [vx + r8*8]
xor rcx, rcx
map_v_xs:
mov rax, [xs + rcx*8]
cmp rax, r13
je map_v_xf
inc rcx
jmp map_v_xs
map_v_xf:
mov edx, [xs_to_col + rcx*4]
mov [thincol + r8*4], edx
mov r13, [vy + r8*8]
xor rcx, rcx
map_v_ys:
mov rax, [ys + rcx*8]
cmp rax, r13
je map_v_yf
inc rcx
jmp map_v_ys
map_v_yf:
mov edx, [ys_to_row + rcx*4]
mov [thinrow + r8*4], edx
inc r8
jmp map_v
map_v_done:
; classify edges into vertical / horizontal
xor r8, r8
xor r12, r12 ; ve count
xor r13, r13 ; he count
gen_edges:
cmp r8, [n_v]
jge gen_edges_done
mov r9, r8
inc r9
cmp r9, [n_v]
jne ge_nowrap
xor r9, r9
ge_nowrap:
mov r10, [vx + r8*8]
mov r11, [vx + r9*8]
cmp r10, r11
je ge_vert
mov rax, [vy + r8*8]
mov [hey + r13*8], rax
mov rcx, r10
mov rdx, r11
cmp rcx, rdx
jle ge_h_ok
xchg rcx, rdx
ge_h_ok:
mov [hexlo + r13*8], rcx
mov [hexhi + r13*8], rdx
inc r13
jmp ge_next
ge_vert:
mov [vex + r12*8], r10
mov rcx, [vy + r8*8]
mov rdx, [vy + r9*8]
cmp rcx, rdx
jle ge_v_ok
xchg rcx, rdx
ge_v_ok:
mov [veylo + r12*8], rcx
mov [veyhi + r12*8], rdx
inc r12
ge_next:
inc r8
jmp gen_edges
gen_edges_done:
mov [ve_cnt], r12
mov [he_cnt], r13
; 2D prefix sum of unfilled cells
xor r15, r15 ; refined row r
pref_r:
cmp r15, [r_cnt]
jge pref_done
mov r13, [row_lo + r15*8] ; py
xor r14, r14 ; refined col c
pref_c:
cmp r14, [c_cnt]
jge pref_c_done
mov rdi, [col_lo + r14*8]
mov rsi, r13
call filled
mov rbx, 1
sub rbx, rax ; unfilled indicator
mov rax, r15
imul rax, [cp1] ; r*cp1
mov rcx, rax
add rcx, r14
add rcx, 1
mov edx, [pref + rcx*4] ; P[r][c+1]
mov rcx, rax
add rcx, r14
mov r8d, [pref + rcx*4] ; P[r][c]
mov rcx, rax
add rcx, [cp1]
mov r9, rcx ; (r+1)*cp1
add rcx, r14
mov r10d, [pref + rcx*4] ; P[r+1][c]
mov eax, ebx
add eax, edx
add eax, r10d
sub eax, r8d
mov rcx, r9
add rcx, r14
add rcx, 1
mov [pref + rcx*4], eax ; P[r+1][c+1]
inc r14
jmp pref_c
pref_c_done:
inc r15
jmp pref_r
pref_done:
; all pairs: part 1 = max area, part 2 = max area fully inside
mov qword [best1], 0
mov qword [best2], 0
xor r8, r8
pair_i:
cmp r8, [n_v]
jge pair_done
mov r12d, [thincol + r8*4]
mov r13d, [thinrow + r8*4]
mov r14, [vx + r8*8]
mov r15, [vy + r8*8]
lea r9, [r8 + 1]
pair_j:
cmp r9, [n_v]
jge pair_j_done
; area = (|xi-xj| + 1) * (|yi-yj| + 1)
mov rax, r14
sub rax, [vx + r9*8]
jns .ax
neg rax
.ax:
inc rax
mov rbx, rax
mov rax, r15
sub rax, [vy + r9*8]
jns .ay
neg rax
.ay:
inc rax
imul rax, rbx
cmp rax, [best1]
jle .no1
mov [best1], rax
.no1:
push rax ; save area
; refined block: c1,c2 then r1,r2
mov eax, [thincol + r9*4]
mov ecx, r12d
cmp ecx, eax
jle .cc
xchg ecx, eax
.cc:
mov edi, ecx ; c1
mov esi, eax ; c2
mov eax, [thinrow + r9*4]
mov ecx, r13d
cmp ecx, eax
jle .rr
xchg ecx, eax
.rr:
mov edx, ecx ; r1
mov ecx, eax ; r2
call block_unf
pop rbx ; area
test eax, eax
jnz .no2 ; contains unfilled cells
cmp rbx, [best2]
jle .no2
mov [best2], rbx
.no2:
inc r9
jmp pair_j
pair_j_done:
inc r8
jmp pair_i
pair_done:
print_results:
mov rcx, label1
call print_string
mov rax, [best1]
call print_int64
call print_newline
mov rcx, label2
call print_string
mov rax, [best2]
call print_int64
call print_newline
mov rax, SYS_EXIT
xor rdi, rdi
syscall
; filled: is tile (RDI=px, RSI=py) red or green (inside or on the loop)?
; Output: RAX = 1 if filled, else 0. Clobbers RAX, RCX, RDX, R10, R11.
filled:
xor ecx, ecx ; on-edge flag
xor r11, r11 ; crossing count
xor r10, r10 ; edge index
.v_loop:
cmp r10, [ve_cnt]
jge .v_done
mov rax, [vex + r10*8]
cmp rax, rdi
jne .v_cross
mov rdx, [veylo + r10*8]
cmp rsi, rdx
jl .v_cross
mov rdx, [veyhi + r10*8]
cmp rsi, rdx
jg .v_cross
mov ecx, 1 ; on a vertical edge
.v_cross:
mov rax, [vex + r10*8]
cmp rax, rdi
jle .v_next
mov rdx, [veylo + r10*8]
cmp rsi, rdx
jl .v_next
mov rdx, [veyhi + r10*8]
cmp rsi, rdx
jge .v_next
inc r11
.v_next:
inc r10
jmp .v_loop
.v_done:
test ecx, ecx
jnz .yes
xor r10, r10
.h_loop:
cmp r10, [he_cnt]
jge .h_done
mov rax, [hey + r10*8]
cmp rax, rsi
jne .h_next
mov rdx, [hexlo + r10*8]
cmp rdi, rdx
jl .h_next
mov rdx, [hexhi + r10*8]
cmp rdi, rdx
jg .h_next
jmp .yes
.h_next:
inc r10
jmp .h_loop
.h_done:
mov rax, r11
and rax, 1
ret
.yes:
mov rax, 1
ret
; block_unf: count of unfilled refined cells in [c1,c2] x [r1,r2].
; In: RDI=c1, RSI=c2, RDX=r1, RCX=r2. Out: EAX. Clobbers RAX, R10, R11.
block_unf:
mov r10, rcx
inc r10
imul r10, [cp1] ; (r2+1)*cp1
mov r11, r10
add r11, rsi
add r11, 1
mov eax, [pref + r11*4] ; A
mov r11, r10
add r11, rdi
sub eax, [pref + r11*4] ; - C
mov r10, rdx
imul r10, [cp1] ; r1*cp1
mov r11, r10
add r11, rsi
add r11, 1
sub eax, [pref + r11*4] ; - B
mov r11, r10
add r11, rdi
add eax, [pref + r11*4] ; + D
ret
; sort_q: insertion sort of qword array RDI[0..RSI-1] ascending.
; Clobbers RAX, RDX, R8, R9, R10.
sort_q:
mov r8, 1
.i:
cmp r8, rsi
jge .done
mov r10, [rdi + r8*8]
mov r9, r8
dec r9
.j:
cmp r9, 0
jl .place
mov rax, [rdi + r9*8]
cmp rax, r10
jle .place
mov rdx, r9
inc rdx
mov [rdi + rdx*8], rax
dec r9
jmp .j
.place:
mov rdx, r9
inc rdx
mov [rdi + rdx*8], r10
inc r8
jmp .i
.done:
ret
; dedup_q: remove consecutive duplicates in sorted RDI[0..RSI-1].
; Out: RAX = new length. Clobbers RAX, RCX, RDX, R8.
dedup_q:
xor rax, rax
xor rcx, rcx
.loop:
cmp rcx, rsi
jge .done
test rax, rax
jz .keep
mov rdx, [rdi + rcx*8]
mov r8, rax
dec r8
cmp rdx, [rdi + r8*8]
je .skip
.keep:
mov rdx, [rdi + rcx*8]
mov [rdi + rax*8], rdx
inc rax
.skip:
inc rcx
jmp .loop
.done:
ret
|