uses heap; fn main [ 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 move_back := empty(tuple5(int, int, int, int, int)); var on_best_path := array_fill(false, [x, y, 3, 3]); var min_hl := array_fill(-1, [x, y, 3, 3]); var pending := heap_from_list([ mktuple5(0, xp, yp, 1, 0) ]); while heap_is_nonempty(pending) do [ var s : tuple5(int, int, int, int, int); pending, s := heap_extract(pending); if min_hl[s.v2, s.v3, s.v4 + 1, s.v5 + 1] <> -1 then continue; min_hl[s.v2, s.v3, s.v4 + 1, s.v5 + 1] := s.v1; if s.v2 = xe, s.v3 = ye then [ if len(move_back) = 0 then [ move_back += [ mktuple5(s.v1, s.v2, s.v3, s.v4, s.v5) ]; move_back += [ mktuple5(s.v1, s.v2, s.v3, s.v5, -s.v4) ]; move_back += [ mktuple5(s.v1, s.v2, s.v3, -s.v5, s.v4) ]; move_back += [ mktuple5(s.v1, s.v2, s.v3, -s.v4, -s.v5) ]; ] ] var xn, yn := s.v2 + s.v4, s.v3 + s.v5; if a[xn, yn] = '.' then pending := heap_insert(pending, mktuple5(s.v1 + 1, xn, yn, s.v4, s.v5)); pending := heap_insert(pending, mktuple5(s.v1 + 1000, s.v2, s.v3, s.v5, -s.v4)); pending := heap_insert(pending, mktuple5(s.v1 + 1000, s.v2, s.v3, -s.v5, s.v4)); ] while len_greater_than(move_back, 0) do [ var s := move_back[0]; move_back := move_back[1 .. ]; if on_best_path[s.v2, s.v3, s.v4 + 1, s.v5 + 1] then continue; on_best_path[s.v2, s.v3, s.v4 + 1, s.v5 + 1] := true; if s.v2 = xp, s.v3 = yp then continue; var xn, yn := s.v2 - s.v4, s.v3 - s.v5; if min_hl[xn, yn, s.v4 + 1, s.v5 + 1] = s.v1 - 1 then move_back +<= mktuple5(s.v1 - 1, xn, yn, s.v4, s.v5); if min_hl[s.v2, s.v3, s.v5 + 1, -s.v4 + 1] = s.v1 - 1000 then move_back +<= mktuple5(s.v1 - 1000, s.v2, s.v3, s.v5, -s.v4); if min_hl[s.v2, s.v3, -s.v5 + 1, s.v4 + 1] = s.v1 - 1000 then move_back +<= mktuple5(s.v1 - 1000, s.v2, s.v3, -s.v5, s.v4); ] var sum := 0; for j := 0 to y do [ for i := 0 to x do [ for l := 0 to 3 do [ for k := 0 to 3 do [ if on_best_path[i, j, k, l] then [ sum += 1; goto next_position; ] ] ] next_position: ] ] write(h[1], ntos(sum) + nl); ]