diff --git a/17/main.s b/17/main.s new file mode 100644 index 0000000..abb6b5c --- /dev/null +++ b/17/main.s @@ -0,0 +1,422 @@ +%include "utils.s" + +global _start +[bits 32] +[section .text] + +; len +2 for padding +%define LINE_LEN (141+2) +%define FILENAME "input" +;%define LINE_LEN (13+2) +;%define FILENAME "input_test" + +%define DBG_PRINT + +_start: + +; convert input file to useful data +mov esi, file +mov edi, cost +convert_input: +lodsb +cmp al, 10 ; \n +je .cont +cmp al, '$' +jne .num +mov al, 0xFF +stosb +jmp .cont +.num: +sub al, '0' +stosb +.cont: +cmp esi, file.over +jb convert_input + +; im lazy so doing dijkstra +; thanks wikipedia + +; for each vertex v in Graph.Vertices: +; dist[v] ← INFINITY +; prev[v] ← UNDEFINED +; add v to Q +mov ecx, LINE_LEN*LINE_LEN*32 +mov eax, 0xffffffff +mov edi, dist +rep stosd +mov ecx, LINE_LEN*LINE_LEN*32 +mov eax, 0xffffffff +mov edi, prev +rep stosd +mov ecx, LINE_LEN*LINE_LEN*32 +mov eax, 1 +mov edi, q +rep stosb + +; for all real dir: +; dist[source@dir] ← 0 +mov dword [dist+((((LINE_LEN*32)+(32*1)))|0b00_000)*4], 0 +mov dword [dist+((((1*(LINE_LEN*32))+(32*1)))|0b10_000)*4], 0 + + + +; while Q is not empty and any dist[u] in Q < inf: +; u ← vertex in Q with min dist[u] +while_q: +xor ebp, ebp ; test node +mov ecx, 0xffffffff ; best dist +mov edx, 0xffffffff ; best node +.find_min: +cmp byte [q+ebp], 1 +jne .cont +cmp [dist+ebp*4], ecx +cmovb ecx, [dist+ebp*4] +cmovb edx, ebp +.cont: +inc ebp +cmp ebp, LINE_LEN*LINE_LEN*32 +jb .find_min +cmp ecx, 0xffffffff +je while_q_done + +%ifdef DBG_PRINT +pushad +call newline +mov ebp, edx +mov eax, edx +xor edx, edx +shr eax, 5 +mov ebx, LINE_LEN +div ebx +call print_dec +call space +mov eax, edx +call print_dec +call space +mov eax, ebp +and eax, 0b11111 +call print_dec +call space +mov eax, ecx +call print_dec +call newline +popad +%endif + +; remove u from Q +mov byte [q+edx], 0 + +; for each neighbor v of u still in Q: +; alt ← dist[u] + Graph.Edges(u, v) +; if alt < dist[v]: +; dist[v] ← alt +; prev[v] ← u +mov ebp, LINE_LEN*32 ; whatever +for_neighbor: +; turning neighbor 0 +neighbor_0: +; neighbors += v@dir(u, ~u.dir & 0b10_000) +mov ebx, edx +not ebx +and ebx, 0b10000 +; tmp := 32 +mov edi, 32 +; bt dir, 4 +bt ebx, 4 +; if CF tmp := LINE_LEN +cmovc edi, ebp +; bt dir, 3 +; if CF tmp := -tmp +mov esi, edi +neg esi +bt ebx, 3 +cmovc edi, esi +mov eax, edi +; v.dir := dir +or edi, ebx +; v := u + tmp +; CheckBounds(v) +; Graph.Edges(u, v) := cost(v) +; v := v + tmp +; CheckBounds(v) +; Graph.Edges(u, v) += cost(v) +; v := v + tmp +; CheckBounds(v) +; Graph.Edges(u, v) += cost(v) +; v := v + tmp +; CheckBounds(v) +; Graph.Edges(u, v) += cost(v) +mov ebx, eax +mov esi, edx +and esi, ~0b11111 +add edi, esi ; v := u + tmp +mov eax, edi +shr eax, 5 +movzx eax, byte [cost+eax] +cmp al, 0xff +je neighbor_1 ; off graph +mov esi, eax ; Graph.Edges(u, v) := cost(v) +add edi, ebx ; v := v + tmp +mov eax, edi +shr eax, 5 +movzx eax, byte [cost+eax] +cmp al, 0xff +je neighbor_1 ; off graph +add esi, eax ; Graph.Edges(u, v) += cost(v) +add edi, ebx ; v := v + tmp +mov eax, edi +shr eax, 5 +movzx eax, byte [cost+eax] +cmp al, 0xff +je neighbor_1 ; off graph +add esi, eax ; Graph.Edges(u, v) += cost(v) +add edi, ebx ; v := v + tmp +mov eax, edi +shr eax, 5 +movzx eax, byte [cost+eax] +cmp al, 0xff +je neighbor_1 ; off graph +add esi, eax ; Graph.Edges(u, v) += cost(v) +; alt ← dist[u] + cost(v) +; if alt < dist[v]: +; dist[v] ← alt +; prev[v] ← u +add esi, ecx +%ifdef DBG_PRINT +pushad +call space +mov esi, eax +mov eax, edi +shr eax, 5 +mov ecx, LINE_LEN +xor edx, edx +div ecx +call print_dec +call space +mov eax, edx +call print_dec +call space +mov eax, edi +and eax, 0x1f +call print_dec +call space +mov eax, esi +call print_dec +call newline +popad +%endif +cmp esi, [dist+edi*4] +jae neighbor_1 ; not better +mov [dist+edi*4], esi +mov [prev+edi*4], edx +; turning neighbor 1 +neighbor_1: +; neighbors += v@dir(u, (~u.dir & 0b10_000) | 0b01_000) +mov ebx, edx +not ebx +and ebx, 0b10000 +or ebx, 0b01000 +; tmp := 32 +mov edi, 32 +; bt dir, 4 +bt ebx, 4 +; if CF tmp := LINE_LEN +cmovc edi, ebp +; bt dir, 3 +; if CF tmp := -tmp +mov esi, edi +neg esi +bt ebx, 3 +cmovc edi, esi +mov eax, edi +; v.dir := dir +or edi, ebx +; v := u + tmp +; CheckBounds(v) +; Graph.Edges(u, v) := cost(v) +; v := v + tmp +; CheckBounds(v) +; Graph.Edges(u, v) += cost(v) +; v := v + tmp +; CheckBounds(v) +; Graph.Edges(u, v) += cost(v) +; v := v + tmp +; CheckBounds(v) +; Graph.Edges(u, v) += cost(v) +mov ebx, eax +mov esi, edx +and esi, ~0b11111 +add edi, esi ; v := u + tmp +mov eax, edi +shr eax, 5 +movzx eax, byte [cost+eax] +cmp al, 0xff +je neighbor_2 ; off graph +mov esi, eax ; Graph.Edges(u, v) := cost(v) +add edi, ebx ; v := v + tmp +mov eax, edi +shr eax, 5 +movzx eax, byte [cost+eax] +cmp al, 0xff +je neighbor_2 ; off graph +add esi, eax ; Graph.Edges(u, v) += cost(v) +add edi, ebx ; v := v + tmp +mov eax, edi +shr eax, 5 +movzx eax, byte [cost+eax] +cmp al, 0xff +je neighbor_2 ; off graph +add esi, eax ; Graph.Edges(u, v) += cost(v) +add edi, ebx ; v := v + tmp +mov eax, edi +shr eax, 5 +movzx eax, byte [cost+eax] +cmp al, 0xff +je neighbor_2 ; off graph +add esi, eax ; Graph.Edges(u, v) += cost(v) +; alt ← dist[u] + cost(v) +; if alt < dist[v]: +; dist[v] ← alt +; prev[v] ← u +add esi, ecx +%ifdef DBG_PRINT +pushad +call space +mov esi, eax +mov eax, edi +shr eax, 5 +mov ecx, LINE_LEN +xor edx, edx +div ecx +call print_dec +call space +mov eax, edx +call print_dec +call space +mov eax, edi +and eax, 0x1f +call print_dec +call space +mov eax, esi +call print_dec +call newline +popad +%endif +cmp esi, [dist+edi*4] +jae neighbor_2 ; not better +mov [dist+edi*4], esi +mov [prev+edi*4], edx +; straight - neighbor 2 +neighbor_2: +mov ebx, edx +and ebx, ~0b11111 +cmp edx, (((LINE_LEN*32)+(32*1))) +je while_q_cont +; if u.dir & 0b00_111 < 6 +; neighbors += v@dir(u, u.dir + 1) +mov ebx, edx +and ebx, 0b00111 +cmp ebx, 6 +jae while_q_cont ; neighbors done +mov ebx, edx +and ebx, 0b11111 +inc ebx +; tmp := 32 +mov edi, 32 +; bt dir, 4 +bt ebx, 4 +; if CF tmp := LINE_LEN +cmovc edi, ebp +; bt dir, 3 +; if CF tmp := -tmp +mov esi, edi +neg esi +bt ebx, 3 +cmovc edi, esi +; v := u + tmp +mov esi, edx +and esi, ~0b11111 +add edi, esi +; v.dir := dir +or edi, ebx +; alt ← dist[u] + cost(v) +; if alt < dist[v]: +; dist[v] ← alt +; prev[v] ← u +mov eax, edi +shr eax, 5 +movzx eax, byte [cost+eax] +cmp al, 0xff +je while_q_cont ; off graph +add eax, ecx +%ifdef DBG_PRINT +pushad +call space +mov esi, eax +mov eax, edi +shr eax, 5 +mov ecx, LINE_LEN +xor edx, edx +div ecx +call print_dec +call space +mov eax, edx +call print_dec +call space +mov eax, edi +and eax, 0x1f +call print_dec +call space +mov eax, esi +call print_dec +call newline +popad +%endif +cmp eax, [dist+edi*4] +jae while_q_cont ; not better +mov [dist+edi*4], eax +mov [prev+edi*4], edx + +while_q_cont: +jmp while_q + +while_q_done: + +call newline + +; last dist values +mov ebx, ((((LINE_LEN-2)*(LINE_LEN*32))+((LINE_LEN-2)*32))+0b00000) +print_last_dist: +mov eax, [dist+ebx*4] +call print_sign_dec +inc ebx +mov ecx, ebx +and ecx, 0b111 +cmp ecx, 0b111 +jne .space +call newline +mov ecx, ebx +and ecx, 0b11111 +cmp ecx, 0b11111 +je .done +inc ebx +jmp .cont +.space: +call space +.cont: +jmp print_last_dist +.done: + +game_over: +jmp exit + +[section .data] +file: incbin FILENAME +.over: + +[section .bss] +dist: resd LINE_LEN*LINE_LEN*32 +prev: resd LINE_LEN*LINE_LEN*32 +q: resb LINE_LEN*LINE_LEN*32 +cost: resb LINE_LEN*LINE_LEN +new_file: resb len(file) diff --git a/17/pseudo b/17/pseudo index aa9df93..67b8038 100644 --- a/17/pseudo +++ b/17/pseudo @@ -1,37 +1,54 @@ -Graph.Edges(u@dir, v@dir) { - ; if cost(v) = 0xff, we're off graph, - ; in the padded area - Graph.Edges := cost(v) -} - v@dir(u, dir) { v.dir := dir - tmp := 1 + tmp := 32 + bt dir, 4 + if CF + tmp := LINE_LEN*32 bt dir, 3 - if CF - tmp := LINE_LEN - bt dir, 2 if CF tmp := -tmp - v := u + tmp + + if dir & 0b0_111 = 0 + v := u + tmp + CheckBounds(v) + Graph.Edges(u, v) := cost(v) + v := v + tmp + CheckBounds(v) + Graph.Edges(u, v) += cost(v) + v := v + tmp + CheckBounds(v) + Graph.Edges(u, v) += cost(v) + v := v + tmp + CheckBounds(v) + Graph.Edges(u, v) += cost(v) + else + v := u + tmp + CheckBounds(v) + Graph.Edges(u, v) := cost(v) } neighbors(u@dir) { ; can always turn - neighbors += v@dir(u, ~u.dir & 0b1000) - neighbors += v@dir(u, (~u.dir & 0b1000) | 0b0100) - ; can go forward if consec < 3 - if u.dir & 0b0011 < 3 + neighbors += v@dir(u, ~u.dir & 0b10_000) + neighbors += v@dir(u, (~u.dir & 0b10_000) | 0b01_000) + ; can go forward if consec < 6 + if u.dir & 0b00_111 < 6 neighbors += v@dir(u, u.dir + 1) } -; 12 possibilities, use 16 so we can do bit hacks -; 0000 0001 0010 0011 0100 0101 0110 0111 -; 0 1 2 3 4 5 6 7 -dir = { R1, R2, R3, XX, L1, L2, L3, XX, -; 1000 1001 1010 1011 1100 1101 1110 1111 -; 8 9 10 11 12 13 14 15 - D1, D2, D3, XX, U1, U2, U3, XX} +; 28 possibilities, use 32 so we can do bit hacks +; 00000 00001 00010 00011 00100 00101 00110 00111 +; 0 1 2 3 4 5 6 7 +dir = { R4, R5, R6, R7, R8, R9, RA, XX, +; 01000 01001 01010 01011 01100 01101 01110 01111 +; 8 9 10 11 12 13 14 15 + L4, L5, L6, L7, L8, L9, LA, XX, +; 10000 10001 10010 10011 10100 10101 10110 10111 +; 16 17 18 19 20 21 22 23 + D4, D5, D6, D7, D8, D9, DA, XX, +; 11000 11001 11010 11011 11100 11101 11110 11111 +; 24 25 26 27 28 29 30 31 + U4, U5, U6, U7, U8, U9, UA, XX} dist[(x,y),dir] prev[(x,y),dir]