如何随机填充一维空间?

时间:2011-10-20 11:55:41

标签: random

我想知道如何随机填充具有一定数量的项目和目标大小的空间,例如,如果列数= 15且目标大小宽度= 320,我如何随机分配列宽度填补空间?如下图所示,如果可能,任何类型的伪代码或算法都可以

enter image description here

2 个答案:

答案 0 :(得分:2)

在15个随机“列”中对320像素进行分区的一种方法是统一进行,即每个列宽都遵循相同的分布。

为此,您实际需要在simplex上进行统一分发。第一种实现的方法是yi_H描述的方式,可能是要走的路:

  • 生成0到320之间的14个统一整数。
  • 继续重新生成已经选择的任何数字,以便最终得到14个不同的数字
  • 对它们进行排序
  • 您的列边界由两个连续的随机数给出。

如果您有最小宽度要求(例如,非空列为1),请将其从320像素中删除15次,生成新范围内的数字并进行必要的调整。

在单纯形上实现统一点的第二种方法是涉及更多,并且不太适合像素这样的离散设置,但在这里它仍然是简短的:

  • 生成具有相同形状参数的15个指数随机变量(例如1)
  • 将每个数字除以总数,以便每个数字都在[0,1]
  • 将这些数字乘以320,然后将它们四舍五入。这些是您的列宽

这不如第一种方式那么好,因为使用舍入可能会以大于或小于320的总数结束,并且您可能有0宽度的列...唯一的优点是您不需要执行任何排序(但你必须计算对数...所以总而言之,第一种方式是要走的路)。

我应该补充一点,如果您不一定要统一随机填充,那么您可以使用更多算法。

编辑:以下是Mathematica中第一个算法的快速实现。请注意,为了避免在它们全部不同之前生成点,您可以只考虑空列的宽度为1,然后最小宽度为2将为您提供非空内部的列:

min = 2;
total = 320;
height = 50;
n = 15;
x = Sort[RandomInteger[total - n*min - 1, n - 1]] + Range[n - 1]*min
Graphics[{Rectangle[{-2, 0}, {0, height}], (*left margin*)
  Rectangle[{#, 0}, {# + 1, height}] & /@ x, (*columns borders*)
  Rectangle[{total, 0}, {total + 2, height}]}, (*right margin*)
 PlotRange -> {{-2, total + 2}, {0, height}}, 
 ImageSize -> {total + 4, height}]

with给出以下示例输出:

output with 15 columns, minimum width 2

编辑:这是修改后的javascript算法(注意,我之前从未编写过Javascript,因此可能会出现一些错误\风格不佳):

function sortNumber(a,b)
{
   return a - b;
}

function draw() {
   var canvas = document.getElementById( "myCanvas" );

   var numberOfStrips = 15;
   var initPosX = 10;
   var initPosY = 10;
   var width = 320;
   var height = 240;
   var minColWidth = 2;
   var reducedWidth = width - numberOfStrips * minColWidth;
   var separators = new Array();

   for ( var n = 0; n < numberOfStrips - 1; n++ ) {
      separators[n] = Math.floor(Math.random() * reducedWidth);
   }
   separators.sort(sortNumber);
   for ( var n = 0; n < numberOfStrips - 1; n++ ) {
      separators[n] += (n+1) * minColWidth;
   }
   if ( canvas.getContext ) {
      var ctx = canvas.getContext( "2d" );

      // Draw lines
      ctx.lineWidth = 1;
      ctx.strokeStyle = "rgb( 120, 120, 120 )";
      for ( var n = 0; n < numberOfStrips - 1; n++ ) {
         var newPosX = separators[n];
         ctx.moveTo( initPosX + newPosX, initPosY );
         ctx.lineTo( initPosX + newPosX, initPosY + height );
      }
      ctx.stroke();

      // Draw enclosing rectangle
      ctx.lineWidth = 4;
      ctx.strokeStyle = "rgb( 0, 0, 0 )";
      ctx.strokeRect( initPosX, initPosY, width, height );
   }
}

此外,请注意minColWidth不应大于某个值(reducedWidth不应为负值...),但未在算法中进行测试。如前所述,如果您不介意彼此相交两条线,则值为0;如果您不介意彼此相邻的两条线,则值为1;如果您不需要,则值为2或更大只有空栏。

答案 1 :(得分:1)

在范围(0,320)中创建14个唯一数字。这些将是酒吧的x位置。

创建随机数,与之前的数字进行比较,存储它。

如果不允许连续的行,也要检查它是否与之前的任何+ -1相等。