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 xf := 1 to x - 1 do [ for yf := 1 to y - 1 do [ if a[xf, yf] = '#' or start_to_end[xf, yf] < 0 then continue; for xt := 1 to x - 1 do [ for yt := 1 to y - 1 do [ if a[xt, yt] = '#' or end_to_start[xt, yt] < 0 then continue; var dist := abs(xt - xf) + abs(yt - yf); if dist > 20 then continue; var saved := distance - (end_to_start[xt, yt] + start_to_end[xf, yf] + dist); if saved >= threshold then result += 1; ] ] ] ] write(h[1], ntos(result) + nl); ]