Last active
August 19, 2021 10:29
-
-
Save BrightSoul/da12c3581ae390521684cee56235e7ce to your computer and use it in GitHub Desktop.
C# solution to AlgoExpert's RemoveIslands problem as seen here: https://www.youtube.com/watch?v=4tYoVx0QoN0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Drawing; | |
namespace RemoveIslandsProblem | |
{ | |
class Program | |
{ | |
private const int ArraySize = 6; | |
static void Main(string[] args) | |
{ | |
bool[,] input = GenerateMatrix(); | |
bool[,] output = RemoveIslands(input); | |
PrintMatrix(input); | |
PrintMatrix(output); | |
} | |
private static bool[,] RemoveIslands(bool[,] matrix) | |
{ | |
int xLength = matrix.GetLength(0); | |
int yLength = matrix.GetLength(1); | |
bool[,] output = new bool[xLength, yLength]; | |
HashSet<Point> dockedPoints = new HashSet<Point>(); | |
for (int x = 0; x < xLength; x++) | |
{ | |
for (int y = 0; y < yLength; y++) | |
{ | |
output[x, y] = IsPointDocked(new Point(x, y), matrix, dockedPoints); | |
} | |
} | |
return output; | |
} | |
private static bool IsPointDocked(Point point, bool[,] matrix, HashSet<Point> dockedPoints) | |
{ | |
// Not interested in points with a false value: it sould stay false | |
if (!matrix[point.X, point.Y]) | |
{ | |
return false; | |
} | |
bool isDocked = false; | |
int xUpperBound = matrix.GetLength(0) - 1; | |
int yUpperBound = matrix.GetLength(1) - 1; | |
// Keep track of points we've visited, they will be added to a cache later | |
// if we find they're docked to the border either directly or indirectly | |
HashSet<Point> visitedPoints = new HashSet<Point>(); | |
// Let's keep track of all candidate neighbor points which | |
// we'll have to evaluate in order to find out if they lead to the border | |
Queue<Point> candidatePoints = new Queue<Point>(); | |
// Start evaluating the one we're at | |
candidatePoints.Enqueue(point); | |
while (candidatePoints.TryDequeue(out Point candidatePoint)) | |
{ | |
visitedPoints.Add(candidatePoint); | |
// Great, we reached a point that's on border so our search is over | |
// and x and y coords must be kept | |
if (IsPointOnBorder(candidatePoint, xUpperBound, yUpperBound)) | |
{ | |
isDocked = true; | |
break; | |
} | |
// Otherwise, go visit neighbors | |
Point[] neighborPoints = GetNeighborPoints(candidatePoint); | |
// TODO: Sort neighborPoints so that those closest to known docked points are evaluated first? | |
// May be counter productive though. | |
foreach (Point neighborPoint in neighborPoints) | |
{ | |
// Not interested in neighbor points having a false value | |
if (!matrix[neighborPoint.X, neighborPoint.Y]) | |
{ | |
continue; | |
} | |
// Is this a point we've visited already? | |
// e.g. we don't want to be stuck in a donut forever | |
if (visitedPoints.Contains(neighborPoint)) | |
{ | |
continue; | |
} | |
// Is this neighbor a point we already know is docked to the border? | |
// If so, then our current x,y point is also docked | |
if (dockedPoints.Contains(neighborPoint)) | |
{ | |
isDocked = true; | |
break; | |
} | |
// Enqueue for later evaluation. Maybe one of this | |
// neighbor's neighbors is docked to the border | |
// Since this is a queue, it will be a Depth Search First | |
candidatePoints.Enqueue(neighborPoint); | |
} | |
} | |
if (isDocked) | |
{ | |
// All the points we've visited are docked to the border | |
// add them to a cache so we won't need to visit them again | |
foreach (Point visitedPoint in visitedPoints) | |
{ | |
dockedPoints.Add(visitedPoint); | |
} | |
} | |
return isDocked; | |
} | |
private static Point[] GetNeighborPoints(Point point) | |
{ | |
// Only adjacent neighbors (no diagonal) | |
return new Point[] | |
{ | |
new Point(point.X-1, point.Y), | |
new Point(point.X+1, point.Y), | |
new Point(point.X, point.Y-1), | |
new Point(point.X, point.Y+1) | |
}; | |
} | |
private static bool IsPointOnBorder(Point point, int xUpperBound, int yUpperBound) | |
{ | |
return point.X == 0 || point.Y == 0 || point.X == xUpperBound || point.Y == yUpperBound; | |
} | |
private static void PrintMatrix(bool[,] matrix) | |
{ | |
Console.WriteLine(); | |
for (int x = 0; x < matrix.GetLength(0); x++) | |
{ | |
Console.WriteLine(); | |
for (int y = 0; y < matrix.GetLength(1); y++) | |
{ | |
Console.Write(matrix[x, y] ? '▓' : '░'); | |
} | |
} | |
} | |
private static bool[,] GenerateMatrix() | |
{ | |
bool[,] matrix = new bool[ArraySize, ArraySize]; | |
Random random = new Random(); | |
for (int x = 0; x < matrix.GetLength(0); x++) | |
{ | |
for (int y = 0; y < matrix.GetLength(1); y++) | |
{ | |
matrix[x, y] = random.NextDouble() >= 0.7; | |
} | |
} | |
return matrix; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment