Matthew Heron
Matthew Heron

Reputation: 11

Multiplying a 2d array in its entirety c#

I'm trying to make a 2d array that is double another 2d array. For example, if I had an array that had a height of 2 and a width of 2, the new one would have double the amount. Same goes for its contents: if the original array consisted of 1,0,2,0 I would want the new array to consist of 1,1,0,0,2,2,0,0.
Does anybody know how to do this, or if its possible?

int height = 2;
int width = 2;
int[,] arr1 = new int[height,width];
arr1[0,0] = 0;
arr1[0, 1] = 2;
arr1[1, 0] = 1;
arr1[1, 1] = 0;
int newheight = height * 2;
int newwidth = width * 2;
int[,] newarr = new int[newheight, newwidth];

Upvotes: 0

Views: 71

Answers (2)

TheGeneral
TheGeneral

Reputation: 81473

Ians answer is fine, well apart from using jagged array syntax on a multidimensional array (fixed now).

For academic purposes, I tried to quickly put together a solution that could deal with any size and any dimension.

Unfortunately there is no generic constraint for System.Array so we have to live with casting (somewhere). Also, It could likely be made a little more efficient.

Given

public static Array Inflate<T>(Array source, int size)
{
   // get the lengths of each dimension multiplied by the inflation size
   var lengths = Enumerable
      .Range(0, source.Rank)
      .Select(x => source.GetLength(x) * size)
      .ToArray();

   var indices = new int[source.Rank]; // this is the index map of what we want to set
   var originals = new int[source.Rank]; // this is the index map of the array to interpolate from

   // this is how we create an array of with arbitrary dimensions
   var instance = Array.CreateInstance(typeof(T), lengths);

   do
   {
      // GetValue and SetValue takes an index map
      instance.SetValue(source.GetValue(originals), indices); 

      // this increments each element in the dimension
      // when it hits the last element, goes to the next dimension
      // and increments that, setting the last to 0
      // you can think of it like an minutes, hour, day, type clock
      for (var i = 0; i < lengths.Length; i++)
      {
         indices[i]++;
         originals[i] = indices[i] / size; // original index
         if (indices[i] < lengths[i])
            break;
         indices[i] = originals[i] = 0;
      }
      // if we are back to 0, we have finished
   } while (indices.Any(x => x != 0));
   return  instance;
}

Test Data

var arr1 = new int[2, 2, 2];
arr1[0, 0, 0] = 0;
arr1[1, 0, 0] = 1;
arr1[0, 1, 0] = 2;
arr1[1, 1, 0] = 3;
arr1[0, 0, 1] = 4;
arr1[1, 0, 1] = 5;
arr1[0, 1, 1] = 6;
arr1[1, 1, 1] = 7;

Usage

// inflate a 3 dimensional array by 2 in each dimension
var result = (int[,,])Inflate<int>(arr1, 2);

Printing the results

Word of warning this is a brain twister, as conceptually we are trying to print a third dimension on to a 2 dimensional console. So I am basically just slicing the 3rd dimension (z)

for (var z = 0; z < result.GetLength(2); z++)
{
   Console.WriteLine($"z = {z}");
   for (int x = 0; x < result.GetLength(0); x++)
   {
      for (int y = 0; y < result.GetLength(1); y++)
      {
         Console.Write(result[x,y,z] + " ");
      }
      Console.WriteLine();
   }
}

Output

z = 0

0 0 2 2
0 0 2 2
1 1 3 3
1 1 3 3

z = 1

0 0 2 2
0 0 2 2
1 1 3 3
1 1 3 3

z = 2

4 4 6 6
4 4 6 6
5 5 7 7
5 5 7 7

z = 3

4 4 6 6
4 4 6 6
5 5 7 7
5 5 7 7

Upvotes: 0

Ian
Ian

Reputation: 1504

So if your original looks like:

0 2
1 0

And you want your new one to look like this?

0 0 2 2
0 0 2 2
1 1 0 0
1 1 0 0

Sure, then just use every value twice:

int[,] newarr = new int[newheight, newwidth];
for(int i=0;i<newheight;i++)
{
    for(int j=0;j<newwidth;j++)
    {
        // Divide index by 2 to ensure we don't overflow original array
        newarr[i,j] = arr[i/2, j/2];
    }
}

Upvotes: 1

Related Questions