我有一个值,比如20010.我想在24小时内随机分配这个值.因此,基本上将值拆分为24个大插槽,其中所有插槽都是随机大的.
使用C#解决这个问题的好方法是什么?
mjv*_*mjv 24
随机抽取23(不是24)个数字(不重复),范围为1到20009.在列表中添加0和20010并对这些数字进行排序,每两个连续数字之间的差值为您提供一个时隙值.
也可以通过一次绘制一个值并从"罐"中减去它来进行在线处理,当数量大于剩余量时重新绘制.然而,这种方法可能导致槽的尺寸偏差更大.
dah*_*byk 23
这是使用mjv算法的功能解决方案:
static int[] GetSlots(int slots, int max)
{
return new Random().Values(1, max)
.Take(slots - 1)
.Append(0, max)
.OrderBy(i => i)
.Pairwise((x, y) => y - x)
.ToArray();
}
public static IEnumerable<int> Values(this Random random, int minValue, int maxValue)
{
while (true)
yield return random.Next(minValue, maxValue);
}
public static IEnumerable<TResult> Pairwise<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TSource, TResult> resultSelector)
{
TSource previous = default(TSource);
using (var it = source.GetEnumerator())
{
if (it.MoveNext())
previous = it.Current;
while (it.MoveNext())
yield return resultSelector(previous, previous = it.Current);
}
}
public static IEnumerable<T> Append<T>(this IEnumerable<T> source, params T[] args)
{
return source.Concat(args);
}
Run Code Online (Sandbox Code Playgroud)
Bev*_*van 11
假设您不希望对大小的分布有太多(任何)控制,这里有一种可行的方法(伪代码).
笔记
这很好玩.受David启发,这里是仅使用LINQ提供的运算符实现mjv的解决方案.由于David的Dictionary键只是一个索引,我们可以使用数组代替Pairwise功能:
var r = new Random();
var a = Enumerable.Repeat(null, n - 1) // Seq with (n-1) elements...
.Select(x => r.Next(1, m)) // ...mapped to random values
.Concat(new [] { 0, m })
.OrderBy(x => x)
.ToArray();
return a.Skip(1).Select((x,i) => x - a[i]);
Run Code Online (Sandbox Code Playgroud)