问题
给定一个列表L:[a,b,c,d,e,f]
,是否有随机打乱列表元素的内置方式?就像是:
M:random_order(L);
> [ b, c, d, a, e, f]
我检查了列表的函数和变量的文档,以了解任何用于打乱列表中元素顺序的内置选项,但没有看到任何明显的东西。
语境
我正在尝试生成x
最大总和为的术语列表s
。现在,我通过创建一个列表来做到这一点,其中每个项都是介于 1 和最大值之间的随机数,以确保如果剩余项的最小值为 1,那么总和最多为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
);
但是,这会生成列表,其中较早的术语(即较低的索引)具有较高值的概率较高;而我想要更均匀的值分布。
我能想到的最简单的解决方案就是简单地打乱vals
列表的元素;但是,我同样对任何其他实现此预期结果的方法感兴趣(即x
总和最多为 的术语列表s
)。
更广泛的背景是将数轴的区间划分为子区间的问题。我决定将区间的长度和分区的数量作为构建子区间的变量,从而达到上述目标。如果I = [a, b]
是完整区间,那么对于任何c
,d
这样c+d =< b-a
我们就可以定义子区间[a, a+c]
,[a+c, a+c+d]
,[a+c+d, b]