Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Need help with algorithm to resolve index through jagged array

Tags:

c#

algorithm

Argh! I know I will get this eventually but at this point I'm almost 2 hours into it and still stuck.

I need to resolve the individual indexes for each "level" of a jagged array for a specific location. It's hard to explain, but if you imagine a 3 level jagged array with [2,3,4] lengths. If you then were to flatten that out into a single array it would have a size of 24. Now, let's say you needed to find the the indexes (one for each level of the jagged array) that would be equal to the single array index 22. It would be 1,2,1. It's not hard to figure out a single scenario, but I'm trying to figure out what the algorithm is to resolve these values for a variable depth jagged array.

Here is a simple code sample of my current attempt:

using System;

class Program
{
    static void Main(string[] args)
    {
        //  Build up the data and info about level depth
        int[] levelDepth = new[] { 2, 3, 4 };
        int[][][] data = new int[][][]
        {
            new int[][] { new int[4], new int[4], new int[4] },
            new int[][] { new int[4], new int[4], new int[4] }
        };

        int requestedValue = 22;
        float temp = requestedValue;

        //  Store the index of each level array to get to the index 
        //  for the requested value
        int[] levelIndexes = new int[3] { 0, 0, 0 };

        //  The following does not work!
        int i = levelDepth.Length;
        while (i > 0)
        {
            temp = temp / levelDepth[i - 1];
            levelIndexes[i - 1] = (int)Math.Round(temp);

            i--;
        }
    }
}

It doesn't work correctly, although it ALMOST gets me what I need but I think that just may be luck. I suspect this is a common problem that has been solved before, I just don't have the experience to figure it out. :(

Also, before anyone tells me that using arrays like this is terrible or "why don't you store your data like this" - The above description and code is simulating the layout of some decoder chips on our hardware and I need to work out a way to resolve a path to a specific graph of cascading chips; the above example exactly matches the layout of the chips. I'm stuck with it.

like image 518
scubasteve Avatar asked Aug 24 '11 07:08

scubasteve


2 Answers

You shouldn't use floats here.

int[] levelDepth = new[] { 2, 3, 4 };
int requestedValue = 22;
int[] levelIndexes = new int[levelDepth.Length];


for (int i = 0; i < levelDepth.Length; i++)
{
  // need to go from { 2, 3, 4 } -> { 3*4, 4, 1 }
  int f = 1;
  for (int j = i+1; j < levelDepth.Length; j++)      
     f *= levelDepth[j];

  levelIndexes[i] = requestedValue / f;  // integer divide
  requestedValue = requestedValue % f;
}
like image 91
Henk Holterman Avatar answered Sep 21 '22 21:09

Henk Holterman


Assuming you need the element's value at that point (and not the specific indices), you can simply perform a ruby-like flatten, and then access the index directly.

Edit: Sorry for the misunderstanding, maybe this will help. From Microsoft Visual C#.NET 2003 Developers Cookbook (Mark Schmidt):

static int[] GetDimensionIndices(int flatIndex, Array array)
{
    int[] indices = new int[array.Rank];
    int p = 1;
    for(int i = array.Rank - 1; i >= 0; i--)
    {
        indices[i] = (((flatIndex/p)) % (array.GetUpperBound(i)+1));

        if(i > 0)
            p *= array.GetUpperBound(i) + 1;
    }
    return indices;
}
like image 42
drharris Avatar answered Sep 22 '22 21:09

drharris