uses heap; fn main [ var lines := list_break_to_lines(read_lazy(h[0])); const x := select(len(lines) > 25, 7, 71); const y := x; var a := array_fill(len(lines), [x, y]); var c := empty(tuple2(int, int)); for i := 0 to len(lines) do [ var coords := map(list_break(lines[i], ','), ston); a[coords[0], coords[1]] := min(i, a[coords[0], coords[1]]); c +<= mktuple2(coords[0], coords[1]); ] fn simulate(n : int) : bool [ var visited := array_fill(false, [x, y]); var todo := heap_from_list([ mktuple3(0, 0, 0) ]); visited[0, 0] := true; while heap_is_nonempty(todo) do [ var next : tuple3(int, int, int); todo, next := heap_extract(todo); if next.v2 = x - 1, next.v3 = y - 1 then return true; for d in [ [0, 1], [0, -1], [1, 0], [-1, 0] ] do [ var nx := next.v2 + d[0]; var ny := next.v3 + d[1]; if nx < 0 or nx >= x or ny < 0 or ny >= y then continue; if a[nx, ny] <= n then continue; if visited[nx, ny] then continue; visited[nx, ny] := true; todo := heap_insert(todo, mktuple3(next.v1 + 1, nx, ny)); ] ] return false; ] var a1 := 0; var a2 := len(lines); while a1 < a2 do [ var ah := a1 + a2 shr 1; if simulate(ah) then a1 := ah + 1; else a2 := ah; ] write(h[1], ntos(c[a1].v1) + "," + ntos(c[a1].v2) + nl); ]