I have a string of boolean values which represent a square grid.
0100001110000100
I am trying to write validation routine which checks the grid diagonally to ensure that there are no diagonal lines which have more than one '1' value in them.
As you can see from this example, the fifth group has two ones.
In order to do this, I would like to arrange the grid into collections and then check each collection to see if it has more than one '1' value.
Shown below is the the values arranged as a collection, as well as the position of each value in the original string.
0 0
01 4 1
100 8 5 2
0010 12 9 6 3
101 13 10 7
00 14 11
0 15
I have been trying to figure out the mathematical relationship between the string position and which group it belongs to. I have tried all kinds of formulas but I'm not great at maths so I became stumped.
For reference, the method below is the one I used to validate the string horizontally. The solution I want to come up with needs to be something like this, using LINQ and set based operations as opposed to lots of awkward loops. The exercise I am working on is a code kata about placement of turbines in a windfarm.
public bool HorizontalValidate(string windfarm)
{
var farmSize = (int) Math.Sqrt(windfarm.Length);
var rows = Enumerable.Range(0, farmSize)
.Select(x => windfarm.Substring(x * farmSize, farmSize))
.ToList();
if (rows.Select(x => x.Count(y => y == '+')).Max() > 1)
return false;
return true;
}
Here is a link if anyone is interested: Windfarm Kata
If you are looking for left-bottom to right-top diagonals you can exploit the fact all items on a diagonal have constant column + row
value:
var int[][] grid = ...
bool result = grid
.SelectMany((line, row) => line
.Select((item, column) => (item, diag : row + column)))
.Where(pair => pair.item == 1) // Let's keep 1's only
.GroupBy(pair => pair.diag) // required GroupBy
.Any(group => group.Count() > 1);
If you want to query string windfarm
which represents square grid, you can do it as follow:
string windfarm = "0100110010000100";
int n = (int)Math.Sqrt(windfarm.Length);
bool result = windfarm
.Select((c, index) => (item : c - '0', diag : index / n + index % n))
.Where(pair => pair.item == 1)
.GroupBy(pair => pair.diag)
.Any(group => group.Count() > 1);
In case of left-top to right-bottom diagonals we should use row - column
instead of row + column
(or index / n - index % n
instead of index / n + index % n
)