Shuffle a ragged array

A ragged array is an array where each element is an array of unknown number of positive integers.

For example, the following are ragged arrays:

[[1,2,3],,[9,10]]               Shape:  3,1,2
[,,]                      Shape:  1,1,1
[[1,2,3,4,5,6,8]]                  Shape:  7

The following are not ragged arrays:

   Each element will be an array
[]    The array will contain at least 1 element
[[1,2,3],[]]  Each subarray will contain at least 1 integer

You need to input a ragged array, and return a ragged array with the integers shuffled

• The output array must have the same shape as the input array. We define the shape of the array as the length of each subarray.
• Each integer must have an equally likely chance to appear in each possible location.
• You can assume that your language's built-in random is random.

For example, if I passed in: [,[1,2,3],], then [,[4,4,2],] would be a valid output, but [[4,1,3],,] or [,,[1,2,3]] would not.

• Related. – Martin Ender Dec 8 '16 at 21:17
• Will the input always be a 2D array? – Dennis Dec 8 '16 at 22:32

Jelly, 3 bytes in Jelly's codepage

FẊṁ

Explanation:

FẊṁ
F    flatten list
Ẋ   shuffle the output from the previous line
ṁ  unflatten the list, shaping it like…

Because the program is incomplete ( doesn't have a second argument stated), the default is to use the program input; thus causes the output to have the same sublist pattern as the input.

Try it online!

• Wow, unflatten is a neat and unexpected command. – Magic Octopus Urn Dec 8 '16 at 21:58
• Unflatten might not be the best term since the left argument doesn't have to be flat. The mnemonic is mold. – Dennis Dec 8 '16 at 22:21
• @Dennis: Does that mean that it wouldn't work correctly for this challenge on an input ragged array that contained lists as elements, rather than integers (because it'll flatten the inside lists first)? That's a little disappointing, you'd expect it to work regardless of the type that the ragged array had. (Update: I checked, it seems that both F and work for multiple layers of flattening, not just one.) – user62131 Dec 8 '16 at 22:34
• I mean that the left argument of can be anything, not just a flat list. For example: tio.run/nexus/jelly#@/9wZ@P///@jow11FIxidRSijXUUTEC0qY6CWWzs/… – Dennis Dec 8 '16 at 22:40
• Oh, I'd call that an unflatten operation; the left argument is being treated as a flat list (just it happens to contain lists as elements, but those elements are being interpreted as opaque). Actually, I suspect we agree on what unflattening is but disagree on what flattening is… – user62131 Dec 8 '16 at 22:42

PowerShell v2+, 86 bytes

param($n)$a=$n-split'[^\d]'-ne''|sort{random};-join($n-split'\d+'-ne''|%{$_+$a[$i++]}) Works via string manipulation. Input is passed in as a string representing the array, in whatever format works for your language. ;-) -splits out the input on non-digits, sorts them based on the random script block (which will assign a different random weight for each input to the sort), stores that into$a. We then split the input again, this time on digits, and for each one output the current value (usually brackets and commas) string-concatenated with the corresponding number from $a. That's -joined together back into a string, and output is implicit. Examples PS C:\Tools\Scripts\golfing> .\shuffle-a-ragged-array.ps1 "@(@(1,2,3),4)" @(@(3,2,1),4) PS C:\Tools\Scripts\golfing> .\shuffle-a-ragged-array.ps1 "@(@(1,2,3),4)" @(@(1,2,4),3) PS C:\Tools\Scripts\golfing> .\shuffle-a-ragged-array.ps1 "[,[1,2,3],]" [,[2,4,3],] PS C:\Tools\Scripts\golfing> .\shuffle-a-ragged-array.ps1 "[,[1,2,3],]" [,[5,2,1],] PS C:\Tools\Scripts\golfing> .\shuffle-a-ragged-array.ps1 "[,[1,2,3],]" [,[10,2,1],] Python 2, 89 bytes from random import* x=input();r=sum(x,[]);shuffle(r) print[[r.pop()for _ in t]for t in x] Try it online! • I don't know python that well, but couldn't you do shuffle(r=sum(x,[]))? – Conor O'Brien Dec 8 '16 at 22:49 • No, shuffle shuffles in place and returns None. – Dennis Dec 8 '16 at 22:51 JavaScript (ES6), 78 75 bytes x=>x.map(y=>y.map(z=>+s.splice(Math.random()*s.length,1)),s=eval([${x}]))

This is the first time I can remember using .splice() in a code-golf challenge...

You can golf off two bytes by shuffling the array beforehand:

• $m=array_merge(...$i=$_GET[i]); is 25 bytes shorter than$i=$_GET['i'];$m=call_user_func_array('array_merge',$i); and does the same thing. In addition you can drop the {} after the foreach to save 2 more bytes. – user59178 Dec 9 '16 at 12:32 Bash, 63, 58 bytes EDITS: • Optimized sed expression a bit, -5 bytes Note: Bash does not really support multidimensional arrays (they can only be simulated, to some extent), so instead, this program will accept a "serialized" text representation of a rugged array, as depicted in the task description, e.g.: [[1,2,3],,[9,10]], and provide output in the same format. Golfed printf sed 's/\w\+/%d/g'<<<$1 grep -Po '\d+'<<<\$1|shuf

Test

>./shuffle []
[]

>./shuffle [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
[11,12,9,5,3,6,1,15,14,2,13,7,10,8,4]

>./shuffle [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
[9,15,11,10,7,6,1,14,2,3,12,5,4,13,8]

>./shuffle [[1,2,3],,[9,10]]
[[10,2,4],,[3,1]]

>./shuffle [[1,2,3],,[9,10]]
[[3,4,1],,[2,9]]

A nice bonus is that you can feed it rugged arrays of an arbitrary depth:

./shuffle [[1,[2,[3,[99,101]]],,[9,10]]
[[9,[4,[1,[101,2]]],,[3,99]]

and it will still operate correctly.

Try it online !

Octave , 60 bytes

@(a)mat2cell([a{:}](randperm(sum(s=cellfun(@numel,a)))),1,s)

MATLAB, 84 bytes

function b=g(c);a=[c{:}];a=a(randperm(numel(a)));b=mat2cell(a,1,cellfun('length',c))

Java, 368 bytes

interface Z{int w(int i);default Z m(int n,int s){return i->w(i)+i>=n?s:0;}static int[][]f(int[][]r){int L=0,o=0,x,d,e=0;Z u=i->0,v=i->i;for(int[]a:r){d=a.length;L+=d;u=u.m(L,1);v=v.m(L,-d);}int[]c=new int[L];for(;e<L;)c[e++]=(int)(L*Math.random());for(int[]a:r){for(x=0;x<a.length;){d=c[x+o];e=v.w(d);d=u.w(d);L=a[x];a[x++]=r[d][e];r[d][e]=L;}o+=a.length;}return r;}}

the method static int[][] f( int[][] r ){...} solves the challenge. decided to roll my own functional interface to avoid an import and to add in a default method for ease of use

interface Z{ //define my own functional interface instead of importing

int w(int i);

//return a new lambda
//where w(int i) adds the value s
//to the result when i is greater than n
default Z m(int n,int s){
return i->w(i)+i>=n?s:0;
}

static int[][]f(int[][]r){
int L=0,o=0,x,d,e=0;
Z u=i->0, //lambda to convert a flattened index to the input's first dimension index
v=i->i; //lambda to convert a flattened index to the input's second dimension index
for(int[]a:r){
d=a.length;
L+=d; //running total of the lengths
u=u.m(L,1); //increment the 1st conversion by 1 at every array length
v=v.m(L,-d); //decrement the 2nd conversion by the array length after that length
}
int[]c=new int[L]; //will contain flattened index swapping positions
for(;e<L;) //randomize the swap positions
c[e++]=(int)(L*Math.random());
for(int[]a:r){ //swap the elements from the input
for(x=0;x<a.length;){
d=c[x+o]; //flattened swap index
e=v.w(d); //convert swap index to 2nd dimension index
d=u.w(d); //convert swap index to 1st dimension index
L=a[x];
a[x++]=r[d][e];
r[d][e]=L;
}
o+=a.length; //increment offset for flattened index array
}
return r;
}

}