fn test_obstacle(const x y : int, a : array(byte, [x, y]), xp yp dx dy i j : int) : bool [ var visited := array_fill(false, [x, y, 3, 3]); visited[xp, yp, dx + 1, dy + 1] := true; while true do [ var nx, ny := xp + dx, yp + dy; if nx < 0 or nx >= x or ny < 0 or ny >= y then return false; if a[nx, ny] = '#' or nx = i and ny = j then [ dx, dy := -dy, dx; continue; ] xp, yp := nx, ny; if visited[xp, yp, dx + 1, dy + 1] then return true; visited[xp, yp, dx + 1, dy + 1] := true; ] abort; ] fn test_obstacles(const x y : int, a : array(byte, [x, y]), xp yp dx dy i : int) : int [ var count := 0; for j := 0 to y do [ if a[i, j] = 'O' then [ count += select(test_obstacle(a, xp, yp, dx, dy, i, j), 0, 1); ] ] return count; ] 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 dx dy : int; for i := 0 to x do [ for j := 0 to y do [ xp := i; yp := j; if a[i, j] = '^' then [ dx, dy := 0, -1; goto found; ] if a[i, j] = '>' then [ dx, dy := 1, 0; goto found; ] if a[i, j] = 'v' then [ dx, dy := 0, 1; goto found; ] if a[i, j] = '<' then [ dx, dy := -1, 0; goto found; ] ] ] abort; found: a[xp, yp] := '.'; var ixp, iyp := xp, yp; var idx, idy := dx, dy; while true do [ var nx, ny := xp + dx, yp + dy; if nx < 0 or nx >= x or ny < 0 or ny >= y then break; if a[nx, ny] = '#' then [ dx, dy := -dy, dx; continue; ] a[nx, ny] := 'O'; xp, yp := nx, ny; ] var count := 0; for i := 0 to x do [ count += test_obstacles~spark(a, ixp, iyp, idx, idy, i); ] write(h[1], ntos(count) + nl); ]