Search code examples
c#arraysalgorithmlinqlogical-and

How do I run logical 'xnor' across a column in a multi-dimensional array (linq or simple algorithm)?


Currently, I have an array of possibilities, and I am looking to calculate the facts (logical XNOR) based on that list of possibilities.

var possibilities = new[] {
    new[] {0, 1, 1, 1, 1, 1, 1, 1},
    new[] {1, 1, 1, 1, 1, 1, 1, 0}
}

I am trying to convert that into a boolean array of XNOR (all values equal)

Expected Result:

[ 0, 1, 1, 1, 1, 1, 1, 0 ]

The number of possibilities is 1 .. n. Another example would be:

var possibilities = new[] {
    new[] {1, 1, 0, 1, 1, 0, 0, 0},
    new[] {1, 1, 0, 1, 1, 0, 0, 1},
    new[] {0, 1, 1, 0, 1, 1, 0, 1}
}

Where result would be:

[ 0, 1, 0, 0, 1, 0, 1, 0 ]

My original approach was to start building nested loops and iterating over each possibility, grabbing the index and comparing it, however that seemed very 'hackish', and I believe there is a simpler (better) way of handling it via LINQ (however I do not know LINQ well enough to write it) or an algorithm that doesn't require ugly nested loops.

Edit #1: Incorrect 'logic' term used

As mentioned in the answer below, the correct logic was not in fact AND rather XNOR (where all the columns are equal). AND would, in fact, produce 0 where all the columns were 0 when I was (as noted above), was really looking for a result of 1 (or true) if all the values were equal.


Solution

  • int size = possibilities[0].Length;
    int i = 0;
    var a = possibilities.SelectMany(x => x).GroupBy(x => i++ % size)
                  .Select(x => x.Any(z => z == 0) ? 0 : 1);
    

    And Using loops:

    int j = 0, size = possibilities[0].Length;
    int[] result = new int[size];
    for (int i = 0; i < size; i++)
    { 
         for (j = 0; j < possibilities.Length; j++)
             if (possibilities[j][i] == 0) { result[i] = 0; break; }
         if (j == possibilities.Length) result [i] = 1;
    }
    

    XNOR:

    int i = 0;
    var a = possibilities.SelectMany(x => x).GroupBy(x => i++ % size)
                .Select(x => x.All(z => z == 0) || x.All(z => z == 1) ? 1 : 0);
    

    XNOR with loops:

    int size = possibilities[0].Length;
    int[] result = new int[size];
    for (int i = 0; i < size; i++)
    { 
         int q = possibilities[0][i];
         for (j = 1; j < possibilities.Length; j++)
             if (possibilities[j][i] != q) { result[i] = 0; break; }
         if (j == possibilities.Length) result[i] = 1;
    }
    

    Live Demo