using System.Collections.Generic;
private const string pattern1 = @"
private const string pattern2 = @"
private const string pattern3 = @"
private const string pattern4 = @"
private const string pattern5 = @"
public static void Main()
bool[,] map = PatternTo2DArray(pattern1);
var rects = ReduceMap(map);
foreach (var rect in rects)
Console.WriteLine("{0}: {{ {1}, {2}, {3}, {4} }}", ((index + 1).ToString().PadLeft(1, '0')), rect.X, rect.Y, rect.Width, rect.Height);
var total = DumpMap(map);
Console.WriteLine("\r\nOptimised Map From: {0} to {1}", total, index);
public static IEnumerable<Rectangle> ReduceMap(bool[,] map)
int width = map.GetLength(0), height = map.GetLength(1);
MapElement[,] bin = new MapElement[width, height];
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
bin[x, y] = new MapElement() { X = x, Y = y, Width = 1, Height = 1, Set = true };
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
for (int xForward = x + 1; xForward < width; xForward++)
if (!bin[xForward, y].Set)
bin[xForward, y].Set = false;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
for (int yDown = y + 1; yDown < height; yDown++)
if (!bin[x, yDown].Set || bin[x, yDown].Width != bin[x, y].Width)
bin[x, yDown].Set = false;
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
yield return new Rectangle(b.X, b.Y, b.Width, b.Height);
public static int DumpMap(bool[,] map)
int width = map.GetLength(0), height = map.GetLength(1);
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
Console.Write(map[x, y] ? "X" : "_");
public static int CountDataPoints(bool[,] map)
int width = map.GetLength(0), height = map.GetLength(1);
for (int y = 0; y < height; y++)
for (int x = 0; x < width; x++)
public static bool[,] PatternTo2DArray(string pattern)
var lines = new List<string>(pattern.Split('\n'));
for (int i = lines.Count - 1; i > -1; i--)
string line = lines[i].TrimEnd('\r');
var @out = new bool[lines[0].Length, lines.Count];
for (int y = 0; y < lines.Count; y++)
for (int x = 0; x < line.Length; x++)
@out[x, y] = !(line[x] == '_');
internal struct MapElement