在不存储所有可能坐标的情况下,在三维空间中拖曳所有点

时间:2017-10-23 20:39:02

标签: java algorithm math multidimensional-array shuffle

我正在编写一个三维元胞自动机。我现在在每一代中迭代它的方式是:

  1. 创建3D空间中所有可能坐标的列表。
  2. 随机播放列表。
  3. 遍历列表,直到访问完所有坐标。
  4. 转到2。
  5. 以下是代码:

    我有一个简单的3整数结构

    public class Coordinate
    {
        public int x;
        public int y;
        public int z;
    
        public Coordinate(int x, int y, int z) {this.x = x; this.y = y; this.z = z;}
    }
    

    然后在某些时候我这样做:

    List<Coordinate> all_coordinates = new ArrayList<>();
    [...]
    for(int z=0 ; z<length ; z++)
    {
        for(int x=0 ; x<diameter ; x++)
        {
            for(int y=0 ; y<diameter ; y++)
            {
                all_coordinates.add(new Coordinate(x,y,z));
            }
        }
    }
    

    然后在主算法中我这样做:

    private void next_generation() 
    { 
        Collections.shuffle(all_coordinates);
        for (int i=0 ; i < all_coordinates.size() ; i++) 
        {
            [...]
        }
    }
    

    问题是,一旦自动机变得太大,包含所有可能点的列表就会变得很大。我需要一种方法来对所有点进行洗牌,而不必将所有可能的点存储在内存中。我应该怎么做呢?

1 个答案:

答案 0 :(得分:3)

执行此操作的一种方法是首先将三维坐标映射到单个维度。假设您的三维尺寸为X,Y和Z.因此您的x坐标从0到X-1等等。您的空间的完整大小为X*Y*Z。我们称之为S

要将3空格中的任何坐标映射到1空格,请使用公式(x*X) + (Y*y) + z

当然,一旦你生成数字,你必须转换回3空间。这是扭转上述转换的简单问题。假设coord是1空格坐标:

x = coord/X
coord = coord % X
y = coord/Y
z = coord % Y

现在,只需使用一个维度,您就可以将问题简化为以伪随机顺序生成从0到S的所有数字,而不会重复。

我至少知道三种方法。最简单的使用multiplicative inverse,如我在此处所示:Given a number, produce another random number that is the same every time and distinct from all other results

当您生成了所有数字后,您可以通过为乘法逆计算选择不同的xm值来“重新洗牌”列表。

在特定范围内创建非重复伪随机序列的另一种方法是使用linear feedback shift register。我没有一个现成的例子,但我已经使用过它们了。要更改顺序(即重新随机播放),请使用不同的参数重新初始化生成器。

您可能也对此问题的答案感兴趣:Unique (non-repeating) random numbers in O(1)?。该用户只需要查找1,000个号码,因此他可以使用表格,并且接受的答案反映了这一点。其他答案涵盖了LFSR,以及设计了特定时期的Linear congruential generator

我提到的所有方法都没有要求你保持很多状态。无论您的范围是20还是20,000,000,您需要维护的状态量都是不变的。

请注意,我上面提到的所有方法都提供了伪随机序列。它们不是真正的随机,但它们可能足够接近随机以满足您的需求。