Skip to content
Snippets Groups Projects
Verified Commit b3b1d17d authored by Dmytro Bogatov's avatar Dmytro Bogatov :two_hearts:
Browse files

Solve Binary Maze.

parent 9ca44a16
Branches
No related tags found
No related merge requests found
using System;
using System.Collections.Generic;
namespace CodingInterview.HackerRank
{
/// <summary>
/// A binary maze is a maze made out of 0s and 1s.
/// Each 1 represents a path through the maze while each 0 represent a blockade.
/// The starting point is represented as a Y and the finish point is represented as X.
/// The objective of this challenge is to find a solution to the maze by stating the direction of each from X to Y by moving through only 1s.
/// If there are many solutions to the maze, find the shortest one.
///
/// https://www.hackerrank.com/contests/computing-society-code-sprint-1/challenges/binary-maze/problem
/// </summary>
public class BinaryMaze
{
/// <summary>
/// Generates a solution to the maze represented as a series of movements
/// </summary>
/// <param name="start">coordinates (i, j) of the starting point (marked by Y)</param>
/// <param name="map">the maz represented as matrix of characters(0, 1, X, Y)</param>
/// <returns>a series of movements describing the shortest path from Y to X</returns>
public List<char> Solve((int i, int j) start, char[,] map)
{
var queue = new Queue<((int i, int j) tile, List<char> path)>();
queue.Enqueue((tile: start, path: new List<char>()));
while (queue.Count > 0)
{
var (location, path) = queue.Dequeue();
if (
location.i < 0 || location.i == map.GetLength(0) ||
location.j < 0 || location.j == map.GetLength(1) ||
map[location.i, location.j] == '0' ||
map[location.i, location.j] == '2'
)
{
continue;
}
if (map[location.i, location.j] == 'X')
{
return path;
}
map[location.i, location.j] = '2';
foreach (var direction in new (int i, int j, char where)[] {
(0, +1, 'r'),
(0, -1, 'l'),
(+1, 0, 'd'),
(-1, 0, 'u')
})
{
var @copy = new List<char>(path);
@copy.Add(direction.where);
queue.Enqueue((
tile: (i: location.i + direction.i, j: location.j + direction.j),
path: @copy
));
}
}
return new List<char>();
}
// HackerRank required me to write primitive parsing
void Entrypoint(String[] args)
{
var cases = Convert.ToInt32(Console.ReadLine());
for (var @case = 0; @case < cases; @case++)
{
var dimensions = Console.ReadLine().Split(' ');
var rows = Convert.ToInt32(dimensions[0]);
var columns = Convert.ToInt32(dimensions[1]);
var map = new char[rows, columns];
(int i, int j) start = (0, 0);
for (var row = 0; row < rows; row++)
{
var rowStrings = Console.ReadLine();
for (var column = 0; column < columns; column++)
{
map[row, column] = rowStrings[column];
if (map[row, column] == 'Y')
{
start = (i: row, j: column);
}
}
}
var path = Solve(start, map);
foreach (var step in path)
{
Console.Write($"{step} ");
}
Console.WriteLine();
}
}
}
}
using Xunit;
namespace CodingInterview.Tests.HackerRank
{
public class BinaryMaze
{
[Fact]
public void TestCaseOne()
{
// From Hacker Rank
VerifySolution(
new char[,] {
{'Y', '0', '0', '0', '0'},
{'1', '1', '1', '0', '0'},
{'0', '0', '1', '0', '0'},
{'0', '0', '1', 'X', '0'}
}, 6, (i: 0, j: 0)
);
}
[Fact]
public void TestCaseTwo()
{
// From Hacker Rank
VerifySolution(
new char[,] {
{'1', '1', '0', 'X', '1', '0'},
{'0', '1', 'Y', '0', '1', '1'},
{'0', '1', '0', '0', '0', '1'},
{'0', '1', '0', '0', '0', '1'},
{'0', '1', '1', '1', '1', '1'},
{'0', '1', '0', '0', '0', '0'},
}, 14, (i: 1, j: 2)
);
}
private void VerifySolution(char[,] map, int shortest, (int i, int j) start)
{
var answer = new CodingInterview.HackerRank.BinaryMaze().Solve(start, map);
Assert.Equal(shortest, answer.Count);
var location = start;
foreach (var step in answer)
{
if (
location.i < 0 || location.i == map.GetLength(0) ||
location.j < 0 || location.j == map.GetLength(1) ||
map[location.i, location.j] == '0'
)
{
Assert.False(true, "illegal tile");
}
switch (step)
{
case 'u':
location = (i: location.i - 1, j: location.j);
break;
case 'd':
location = (i: location.i + 1, j: location.j);
break;
case 'l':
location = (i: location.i, j: location.j - 1);
break;
case 'r':
location = (i: location.i, j: location.j + 1);
break;
default:
Assert.False(true, "unknown step");
break;
}
}
Assert.Equal('X', map[location.i, location.j]);
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment