Question
Given a list L:[a,b,c,d,e,f]
is there a built in way of randomly shuffling the elements of the list? Something like:
M:random_order(L);
> [ b, c, d, a, e, f]
I checked the documentation for Functions and Variables for Lists for any built in option for shuffling the order of elements in a list, but didn't see anything obvious.
Context
I'm trying to generate lists of x
terms whose maximal sum is s
. Right now, I'm doing this by creating a list where each term is a random number between 1 and the max value that ensures that, if the remaining terms have a minimal value of 1, then the sum will be, at most, s
:
/* `x` is the total number of terms; `s` is the max sum */
gen_val(x, s):=block([x:x, s:s, vals:makelist(nul,i,x) ],
/*
the first value is a random integer in [1, (s-x)], if
vals[1] = (s-x), then all remaining terms have to be equal to 1
*/
vals[1]: 1 + random(s-x),
/*
subsequent terms are assigned in the same way, subtracting the sum of
previously assigned values, as well as reserving at least 1 unit for
each remaining term
*/
for i:2 thru x
do vals[i]:1 + random(s-sum(vals[k],k,1,i-1)-(x-i+1)),
/* return the list */
vals
);
However, this generates lists where earlier terms (i.e. lower index) have a higher probability of having higher values; whereas I'd like a more even distribution of the values.
The simplest solution I could think of was simply shuffling the elements of the vals
list; however, I'd be equally interested in any other method that achieves this desired result (i.e. a list of x
terms whose sum is, at most, s
).
The even broader context is the problem of dividing an interval of the number line into sub-intervals. I decided to take the length of the interval and the number of partitions as my variables for building the sub-intervals, hence the goal, stated above. If I = [a, b]
is the full interval, then for any c
, d
such that c+d =< b-a
we can define the subintervals [a, a+c]
, [a+c, a+c+d]
, [a+c+d, b]