fn floodfill(const x y : int, a : array(byte, [x, y]), xp yp : int) : array(int, [x, y]) [ var reachable := array_fill(-1, [x, y]); reachable[xp, yp] := 0; var queue := [ mktuple2(xp, yp) ]; var dist := 1; while len_greater_than(queue, 0) do [ var new_queue := empty(tuple2(int, int)); for i := 0 to len(queue) do [ for d in [ [0, 1], [0, -1], [1, 0], [-1, 0] ] do [ var xn := queue[i].v1 + d[0]; var yn := queue[i].v2 + d[1]; if a[xn, yn] = '#' then continue; if reachable[xn, yn] <> -1 then continue; reachable[xn, yn] := dist; new_queue +<= mktuple2(xn, yn); ] ] queue := new_queue; dist += 1; ] return reachable; ] fn main [ var threshold := 100; if len(args) >= 1 then threshold := ston(args[0]); var lines := list_break_to_lines(read_lazy(h[0])); lines := list_flatten(lines); const x := len(lines[0]); const y := len(lines); var a := list_to_array([x, y], list_join(lines, "")); a := array_flatten(a); var xp, yp, xe, ye := -1, -1, -1, -1; for j := 0 to y do [ for i := 0 to x do [ if a[i, j] = 'S' then [ xp, yp := i, j; a[i, j] := '.'; ] if a[i, j] = 'E' then [ xe, ye := i, j; a[i, j] := '.'; ] ] ] var start_to_end := floodfill(x, y, a, xp, yp); var end_to_start := floodfill(x, y, a, xe, ye); var distance := start_to_end[xe, ye]; var result := 0; for j := 1 to y - 1 do [ for i := 1 to x - 1 do [ if a[i, j] <> '#' then continue; for d in [ [0, 1], [0, -1], [1, 0], [-1, 0] ] do [ var xn := i + d[0]; var yn := j + d[1]; if a[xn, yn] = '#' or end_to_start[xn, yn] < 0 then continue; var from := x * y; for d2 in [ [0, 1], [0, -1], [1, 0], [-1, 0] ] do [ var xf := i + d2[0]; var yf := j + d2[1]; if a[xf, yf] = '#' then continue; if start_to_end[xf, yf] < 0 then continue; from := min(from, start_to_end[xf, yf]); ] var saved := distance - (end_to_start[xn, yn] + from + 2); if saved >= threshold then result += 1; ] ] ] write(h[1], ntos(result) + nl); ]