Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jagged to Multidimensional Array

Tags:

c#

linq

A co-worker and I are currently engaged in a series of coding challenges.

However we like to make things slightly more interesting and golf our answers down (Yes I know, C# is not the greatest golfing language)

Our most recent one involved rotating a cube (int[,]). So eventually we came up with a bet, if I can get this in one line he buys me lunch and vice versa.

After many backspaces and words my mother would hate to hear me say, I finally got it, or so I thought.

I ended up with int[][].

And as far as I can see there is no easy way to convert this to int[,]. so I'm asking if it is actually possible within one line.

EDIT 1

I would post my source code, but then my co-worker could find it and I could lose a free lunch.

like image 529
Darkestlyrics Avatar asked Dec 23 '22 07:12

Darkestlyrics


1 Answers

You'll need at least two lines, one for declaring your result array and one for the actual copying of the data.

You could first flatten your array of array to a single array, and the use Buffer.BlockCopy to copy all data to the result array.

Here's an example:

var source = new int[][] {
    new int[4]{1,2,3,4},
    new int[4]{5,6,7,8},
    new int[4]{1,3,2,1},
    new int[4]{5,4,3,2}
};

var expected = new int[4,4] {
    {1,2,3,4},
    {5,6,7,8},
    {1,3,2,1},
    {5,4,3,2}
};

var result = new int[4, 4];
// count = source.Length * source[0].Length * sizeof(int) = 64, since BlockCopy is byte based
// to be dynamically you could also use System.Runtime.InteropServices.Marshal.SizeOf(source[0][0]) instead of sizeof(int)
Buffer.BlockCopy(source.SelectMany(r => r).ToArray(), 0, result, 0, 64);

result.Dump("result");
expected.Dump("expected");

Result:

enter image description here

If you insist of being fancy: you could call BlockCopy dynamically with an delegate to have that delegate return Object so you can use it for an assignment of an anonymous class, which is apparently in the spirit of your rules, and wrap everything into a collection so you end with a single line monster like this:

var result = new[]{ new int[4, 4] }.Select(x => new { r = x, tmp = Delegate.CreateDelegate(typeof(Action<Array, int, Array, int, int>), typeof(Buffer).GetMethod("BlockCopy")).DynamicInvoke(new Object[]{source.SelectMany(r => r).ToArray(), 0, x, 0, 64})}).First().r;
like image 129
sloth Avatar answered Jan 15 '23 00:01

sloth