from collections import deque import sys input = sys.stdin.readline def sieve(n): is_prime = [True]*(n+1) if n >= 0: is_prime[0] = False if n >= 1: is_prime[1] = False for i in range(2, int(n**0.5) + 1): if is_prime[i]: for j in range(i*i, n+1, i): is_prime[j] = False return is_prime def find_shift(c0, d0, can_loop, is_prime, LIMIT): # if no loop allowed, only x=0 if not can_loop: return 0 if c0<=LIMIT and d0<=LIMIT and is_prime[c0] and is_prime[d0] else None # otherwise scan x>=0 for x in range(LIMIT+1): cc = c0 + x dd = d0 + x if cc <= LIMIT and dd <= LIMIT and is_prime[cc] and is_prime[dd]: return x return None def try_variant(H, W, grid, Sx, Sy, Gx, Gy, DIRS, is_prime, LIMIT): # BFS to get parent pointers and reachable-visited visited = [[False]*W for _ in range(H)] parent = {} q = deque([(Sx, Sy)]) visited[Sx][Sy] = True while q: x, y = q.popleft() for dx, dy in DIRS: nx, ny = x + dx, y + dy if 0 <= nx < H and 0 <= ny < W and not visited[nx][ny] and grid[nx][ny] != '#': visited[nx][ny] = True parent[(nx,ny)] = ((x,y), (dx,dy)) q.append((nx,ny)) # if G unreachable if not visited[Gx][Gy]: return float('inf') # reconstruct one shortest path by following parents path = [] cur = (Gx, Gy) while cur != (Sx, Sy): (px, py), move = parent[cur] path.append(move) cur = (px, py) path.reverse() # count base-path moves A0 = sum(1 for dx,dy in path if dx == 1 and dy == 0) B0 = sum(1 for dx,dy in path if dx == -1 and dy == 0) C0 = sum(1 for dx,dy in path if dx == 0 and dy == 1) D0 = sum(1 for dx,dy in path if dx == 0 and dy == -1) base_len = len(path) # check if vertical/horizontal loops can be inserted anywhere in the component vert_ok = horz_ok = False for x in range(H): for y in range(W): if visited[x][y]: if x+1 < H and visited[x+1][y]: vert_ok = True if y+1 < W and visited[x][y+1]: horz_ok = True if vert_ok and horz_ok: break if vert_ok and horz_ok: break # find minimal x and y x = find_shift(A0, B0, vert_ok, is_prime, LIMIT) if x is None: return float('inf') y = find_shift(C0, D0, horz_ok, is_prime, LIMIT) if y is None: return float('inf') # total = (A0+B0+C0+D0) + 2*(x+y) = base_len + 2*(x+y) return base_len + 2*(x + y) def solve(): H, W = map(int, input().split()) Sx, Sy = map(int, input().split()) Gx, Gy = map(int, input().split()) Sx -= 1; Sy -= 1; Gx -= 1; Gy -= 1 grid = [input().rstrip() for _ in range(H)] # sieve far enough: worst base_len ≤ H*W, loops ≤ +2000 LIMIT = H*W + 2000 is_prime = sieve(LIMIT) # three variants of neighbor order ΔV, ΔH = Gx - Sx, Gy - Sy DIRS1 = [(1,0), (-1,0), (0,1), (0,-1)] # down, up, right, left DIRS2 = [(0,1), (0,-1), (1,0), (-1,0)] # right, left, down, up # goal‐directed first order3 = [] order3.append((1,0) if ΔV>0 else (-1,0)) order3.append((0,1) if ΔH>0 else (0,-1)) for d in [(1,0),(-1,0),(0,1),(0,-1)]: if d not in order3: order3.append(d) DIRS3 = order3 ans = min( try_variant(H,W,grid,Sx,Sy,Gx,Gy,DIRS1,is_prime,LIMIT), try_variant(H,W,grid,Sx,Sy,Gx,Gy,DIRS2,is_prime,LIMIT), try_variant(H,W,grid,Sx,Sy,Gx,Gy,DIRS3,is_prime,LIMIT), ) print(ans if ans < float('inf') else -1) if __name__ == "__main__": solve()