# HackerRank Castle on the Grid Interview preparation kit solution

In this HackerRank Castle on the Grid Interview preparation kit problem you have Given a grid, a start, and a goal, determine the minimum number of moves to get to the goal.

## Problem solution in Python programming.

```import numbers
import math
from collections import namedtuple,deque
class point(namedtuple("point", "i j")):
def __eq__(self,o):
return self.i == o.i and self.j == o.j
def __ne__(self, o):
return self.i != o.i or self.j != o.j
def __lt__(self, o):
return self.i < o.i or self.j < o.j
def __gt__(self, o):
return self.i > o.i or self.j > o.j
def __le__(self, o):
return self.i <= o.i or self.j <= o.j
def __ge__(self, o):
return self.i >= o.i or self.j >= o.j
def __rshift__(self,o):
return self.i >= o.i and self.j >= o.j
def __lshift__(self,o):
return self.i <= o.i and self.j <= o.j
def __hash__(self):
return hash((self.i, self.j))
def __repr__(self):
return 'p(%r, %r)' % self
if isinstance(o, point):
return point.__new__(point,self.i+o.i,self.j+o.j)
if isinstance(o, numbers.Number):
return point.__new__(point,self.i+o,self.j+o)
return NotImplemented
def __sub__(self,o):
if isinstance(o, point):
return point.__new__(point,self.i-o.i,self.j-o.j)
if isinstance(o, numbers.Number):
return point.__new__(point,self.i-o,self.j-o)
return NotImplemented
def inbound(self,a,b=None):
if b is None:
a,b = point(0,0),a
im,ix = sorted([a.i,b.i])
jm,jx = sorted([a.j,b.j])
return im <= self.i and self.i < ix and jm <= self.j and self.j < jx
def distance(self,o):
return abs(self.i-o.i)+abs(self.j-o.j)
#return math.sqrt((self.i-o.i)**2+(self.j-o.j)**2)
def __isub__(self,o):
return self.__sub__(o)
def __neg__(self):
return point.__new__(point,-self.i,-self.j)
def I():
return point.__new__(point,1,0)
def J():
return point.__new__(point,0,1)

class grid(list):
def __getitem__(self, *args, **kwargs):
if isinstance(args[0], point):
return self[args[0].i][args[0].j]
else:
return list.__getitem__(self, *args, **kwargs)
def __setitem__(self, *args, **kwargs):
if isinstance(args[0], point):
self[args[0].i][args[0].j] = args[1]
else:
return list.__setitem__(self, *args, **kwargs)
def __repr__(self):
return "\n".join(["".join(map(lambda x:str(x)[-1],a)) for a in self])

around = (-point.I(),-point.J(),point.J(),point.I())
n = int(input())
b = grid([list(input()) for _ in range(n)])
_ = list(map(int,input().split()))
p = point(_[0],_[1])
f = point(_[2],_[3])
b[p] = "#"
b[f] = "E"
q = deque([(p,0)])

vg = grid([[False for _ in range(len(b[0]))] for _ in range(len(b))])
while len(q):

c,d = q.popleft()

vg[c] = True
#print(c,b[c.i][c.j])
if c == f:
break
if b[c] == ".":
b[c] = "="

for di in around:
pt = c
while True:
pt += di
if pt.inbound(point(0,0) ,point(len(b),len(b[0]))) and (b[pt] == "." or b[pt] == "E") :
q.append((pt,d+1))
vg[pt] = True
if b[pt] == ".":
b[pt] = d+1
else:
break

#print(c,ar)
#print(q)

#print(b)
print(d)```

## Problem solution in Java Programming.

```import java.io.*;
import java.util.*;

public class Solution {

public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter("\n");
int n = scanner.nextInt();

char[][] grid = new char[n][n];

for (int i = 0; i < n; i++) {
String str = scanner.next();
grid[i] = str.toCharArray();
}

String coords = scanner.next();
String[] split = coords.split(" ");
XY start = new XY(Integer.parseInt(split[0]), Integer.parseInt(split[1]));
XY end = new XY(Integer.parseInt(split[2]), Integer.parseInt(split[3]));

Set<XY> visited = new HashSet<XY>();

System.out.println(minSteps(grid, start, end, visited));
}

private static int minSteps(char[][] grid, XY curr, XY end, Set<XY> visited) {
Queue<XY> queue = new LinkedList<XY>();

Queue<Integer> step = new LinkedList<Integer>();

while (!queue.isEmpty()) {
XY nextXY = queue.remove();
int hop = step.remove();

if (nextXY.equals(end)) return hop;

List<XY> next = getNext(grid, nextXY, visited);

for (int i = 0; i < next.size(); i++) {
}
}

return Integer.MAX_VALUE;
}

private static List<XY> getNext(char[][] grid, XY curr, Set<XY> visited) {
List<XY> next = new ArrayList<XY>();

if (curr.dir == null || curr.dir == Dir.Y) {
int x = curr.x;
for (int i = x - 1; i >= 0; i--) {
if (grid[i][curr.y] == 'X') break;

final XY xy = new XY(i, curr.y, Dir.X);
}

for (int i = x + 1; i < grid.length; i++) {
if (grid[i][curr.y] == 'X') break;

final XY xy = new XY(i, curr.y, Dir.X);
}
}

if (curr.dir == null || curr.dir == Dir.X) {
int y = curr.y;

for (int i = y - 1; i >= 0; i--) {
if (grid[curr.x][i] == 'X') break;

final XY xy = new XY(curr.x, i, Dir.Y);
}

for (int i = y + 1; i < grid.length; i++) {
if (grid[curr.x][i] == 'X') break;

final XY xy = new XY(curr.x, i, Dir.Y);
}
}

return next;
}

private static class XY {
int x, y;
Dir dir;

public XY(int x, int y) {
this.x = x;
this.y = y;
dir = null;
}

public XY(int x, int y, Dir dir) {
this.x = x;
this.y = y;
this.dir = dir;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
XY xy = (XY) o;
return x == xy.x && y == xy.y;

}

@Override
public int hashCode() {
return 31 * x + y;
}

@Override
public String toString() {
return "XY{" +
"x=" + x +
", y=" + y +
", dir=" + dir +
'}';
}
}

private enum Dir {
X, Y;
}
}```

### Problem solution in C++ programming.

```#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <deque>
using namespace std;

// -1 for break; 0 for continue; 1 for OK
int func(vector<vector<char>>& vlist, deque<int>& pst, vector<vector<int>>& visited, int tx, int ty, int x1, int y1)
{
int n = vlist.size();

if(tx < 0 || tx >= n || ty < 0 || ty >= n)
return -1;

if(vlist[tx][ty] == 'X')
return -1;

if(visited[tx][ty] == 1)
return 0;
visited[tx][ty] = 1;

pst.push_back(tx  + ty *n);
if(tx == x1 && ty == y1)
return 1;

return 0;
}

int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */

int n;
cin >> n;

vector<vector<char>> vlist;
vector<vector<int>> vvst;
vlist.resize(n);
vvst.resize(n);

for(int i = 0; i < n; i ++)
{
for(int j =0; j < n; j ++)
{
char c;
cin >> c;
vlist[i].push_back(c);
vvst[i].push_back(0);
}
}

int x0, y0, x1, y1;
cin >> x0 >> y0 >> x1 >> y1;

deque<int> pst;
pst.push_back(x0 + n * y0);
int level = 0;

bool found = false;
deque<int> tempst;

while(true)
{
if(pst.empty())
{
pst = tempst;
tempst.clear();
}
if(pst.empty() || found)
break;
level ++;
while(!pst.empty())
{
if(found)
break;

int v = pst.front();
pst.pop_front();

int tx = v % n;
int ty = v / n;

for(int k = tx - 1; k >=0; k --)
{
int rn = func(vlist, tempst, vvst, k, ty, x1, y1);
if(rn == -1)
break;
else if(rn == 1)
{
found = true;
break;
}
}
for(int k = tx + 1; k < n; k ++)
{
int rn = func(vlist, tempst, vvst, k, ty, x1, y1);
if(rn == -1)
break;
else if(rn == 1)
{
found = true;
break;
}
}

for(int k = ty - 1; k >=0; k --)
{
int rn = func(vlist, tempst, vvst, tx, k, x1, y1);
if(rn == -1)
break;
else if(rn == 1)
{
found = true;
break;
}
}
for(int k = ty + 1; k < n; k ++)
{
int rn = func(vlist, tempst, vvst, tx, k, x1, y1);
if(rn == -1)
break;
else if(rn == 1)
{
found = true;
break;
}
}
}
}
cout << level << endl;
return 0;
}```

### Problem solution in C programming.

```#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

typedef struct {
int x;
int y;
} Gridpoint;

int insertGrid(Gridpoint *queue, int x, int y, int wr_ptr) {
queue[wr_ptr].x = x;
queue[wr_ptr].y = y;
wr_ptr += 1;
return wr_ptr;
}

int MovePath(int **grid, int x, int y, int N, int wr_ptr, Gridpoint *queue) {
int step = grid[x][y] + 1;
//printf("(%d, %d). step = %d\n", x, y, step);

// move up
for (int i=x-1;i>=0;i--) {
if (grid[i][y] == -1) {
break;
}
if (grid[i][y] == 0) {
grid[i][y] = step;
wr_ptr = insertGrid(queue, i, y, wr_ptr);
}
}

// move down
for (int i=x+1;i<N;i++) {
if (grid[i][y] == -1) {
break;
}
if (grid[i][y] == 0) {
grid[i][y] = step;
wr_ptr = insertGrid(queue, i, y, wr_ptr);
}
}
// move right
for (int i=y+1;i<N;i++) {
if (grid[x][i] == -1) {
break;
}
if (grid[x][i] == 0) {
grid[x][i] = step;
wr_ptr = insertGrid(queue, x, i, wr_ptr);
}
}
// move left
for (int i=y-1;i>=0;i--) {
if (grid[x][i] == -1) {
break;
}
if (grid[x][i] == 0) {
grid[x][i] = step;
wr_ptr = insertGrid(queue, x, i, wr_ptr);
}
}

return wr_ptr;
}
int main() {

/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int N;
scanf("%d\n", &N);
int **grid = (int **)malloc(sizeof(int *)*N);
char tmp;
for (int i = 0;i<N;i++) {
grid[i] = (int *)malloc(sizeof(int)*N);
for (int j = 0;j<N;j++) {
scanf("%c\n", &tmp);
if (tmp == 'X') {
grid[i][j] = -1;
} else {
grid[i][j] = 0;
}
}
}

int cur_x, cur_y, end_x, end_y;
scanf("%d %d %d %d", &cur_x, &cur_y, &end_x, &end_y);

Gridpoint *queue = (Gridpoint *)malloc(sizeof(Gridpoint) *100);
int wr_ptr = 0;
int rd_ptr = 0;

//printf("(%d, %d) (%d, %d)\n", cur_x, cur_y, end_x, end_y);
// BFS iteratively on all nodes
while (rd_ptr <= wr_ptr) {
wr_ptr = MovePath(grid, cur_x, cur_y, N, wr_ptr, queue);
//printf("wr_ptr = %d\n", wr_ptr);
cur_x = queue[rd_ptr].x;
cur_y = queue[rd_ptr].y;
rd_ptr++;
//printf("(%d, %d). rd_ptr = %d\n", cur_x, cur_y, rd_ptr);
}

printf("%d", grid[end_x][end_y]);
return 0;
}```

### Problem solution in JavaScript programming.

```'use strict';

const fs = require('fs');

process.stdin.resume();
process.stdin.setEncoding('utf-8');

let inputString = '';
let currentLine = 0;

process.stdin.on('data', inputStdin => {
inputString += inputStdin;
});

process.stdin.on('end', function() {
inputString = inputString.replace(/\s*\$/, '')
.split('\n')
.map(str => str.replace(/\s*\$/, ''));

main();
});

return inputString[currentLine++];
}

// Complete the minimumMoves function below.
function minimumMoves(grid, startRow, startCol, goalRow, goalCol) {
// initialize a 2d matrix to track visited nodes and its parents
const visited = Array(grid.length).fill(false).map(_ => Array(grid[0].length).fill(false).map(_ => ({visited: false, parent: null})));

visited[startRow][startCol].visited = true;
console.log(visited);

const rowQueue = [startRow];
const colQueue = [startCol];

let moves = 0;
let parent = null;
while  (rowQueue.length !== 0) {
const row = rowQueue.shift();
const col = colQueue.shift();
if (row === goalRow && col === goalCol) {
parent = visited[row][col].parent;
break;
}
exploreNeighbours(row, col);
}

console.log(visited);
while (parent !== null) {
console.log(parent);
moves++;
parent = visited[parent[0]][parent[1]].parent;
}

return moves;

function exploreNeighbours(row, col) {
// north, south, east, west directon vectors
const dc = [0, 0, -1, +1];
const dr = [-1, +1, 0, 0];

for (let i = 0; i < 4; i++) {
let cc = col;
let rr = row;
while (true) {
cc += dc[i];
rr += dr[i];

// stop at out of bounds
if (cc < 0 || rr < 0) break;
if (rr > grid.length - 1 || cc > grid[0].length - 1) break;

// stop visited or blocked cells
if (visited[rr][cc].visited) continue;
if (grid[rr][cc] === 'X') break;

colQueue.push(cc);
rowQueue.push(rr);
visited[rr][cc].visited = true;
visited[rr][cc].parent = [row, col];
}
}
}
}

function main() {
const ws = fs.createWriteStream(process.env.OUTPUT_PATH);

const n = parseInt(readLine(), 10);

let grid = [];

for (let i = 0; i < n; i++) {
const gridItem = readLine();
grid.push(gridItem);
}

const startXStartY = readLine().split(' ');

const startX = parseInt(startXStartY[0], 10);

const startY = parseInt(startXStartY[1], 10);

const goalX = parseInt(startXStartY[2], 10);

const goalY = parseInt(startXStartY[3], 10);

const result = minimumMoves(grid, startX, startY, goalX, goalY);

ws.write(result + '\n');

ws.end();
}```