当x <1时,如何得到给定索引的(x,y)坐标。 ÿ?

时间:2016-06-11 07:37:11

标签: algorithm haskell

在过去,我经常使用以下类型的循环(Haskell示例):

  upperBoundToTuples :: Int -> [(Int, Int)]
  upperBoundToTuples n = [(x,y) | x <- [0..n], y <- [x+1..n]]

上面的代码产生范围(0,1)..(n,n)的元组,其中对于所有x&lt;收率

我想知道是否有一种有效的方法可以获得给定单个索引的那些(x,y)索引?可能的应用包括GPU上的优化问题,其中不允许循环并且每个线程仅获得索引。

此外,如果2D情况可能,这样的算法可以推广到多维吗?

2 个答案:

答案 0 :(得分:4)

你要求从[0,N(N + 1)/ 2)到对(x,y)的双射,其中0 <= x&lt; y&lt; = N。

这是一种定义它的简单方法(在伪代码中,但转换为Haskell应该很简单):

x0, y0 = i / (N + 1), i % (N + 1)
if x0 < y0 then result = (x0, y0)
else result = (N - 1 - x0, N - y0)

这是N = 6函数的可视化。地图布局在一个长度为N + 1 = 7的行的表中,第一行代表i = 0到6的函数值,下一个i = 7到13,依此类推。如果仔细观察,可以看到前方对角线上方的东西映射到表中的位置,对角线上方或下方的东西可以旋转到后面的条目。

5,6  0,1  0,2  0,3  0,4  0,5  0,6
4,6  4,5  1,2  1,3  1,4  1,5  1,6
3,6  3,5  3,4  2,3  2,4  2,5  2,6

这与此可视化相反:表T的大小(N + 1)乘以(N + 1),T[x, y] = i其中i映射到(x,y) )通过上述功能。

 -   1   2   3   4   5   6
 -   -   9  10  11  12  13
 -   -   -  17  18  19  20
 -   -   -   -  16  15  14
 -   -   -   -   -   8   7
 -   -   -   -   -   -   0
 -   -   -   -   -   -   -

更高的尺寸

这种方法可能会在更高的维度上工作,但我不会立即看到。作为替代方案,这是一个简单但效率低下的方法,可以在任意维度上工作。

首先,请注意从choose(N + 1, k)k的数字0的{​​{1}}长度增加序列N choose(N, k)binomial coefficient )。其中choose(N, k - 1)N结尾。这给出了这个递归函数,它以降序的colexicographical顺序生成序列(再次以伪代码形式):

sequence(N, k, index)
    = []                                           if k == 0
    = sequence(N - 1, k - 1, index) + [N]          if index < choose(N, k - 1)
    = sequence(N - 1, k, index - choose(N, k - 1)) otherwise

此处为sequence(5, 3, index) index介于0和19之间:

 0 -> [3, 4, 5]
 1 -> [2, 4, 5]
 2 -> [1, 4, 5]
 3 -> [0, 4, 5]
 4 -> [2, 3, 5]
 5 -> [1, 3, 5]
 6 -> [0, 3, 5]
 7 -> [1, 2, 5]
 8 -> [0, 2, 5]
 9 -> [0, 1, 5]
10 -> [2, 3, 4]
11 -> [1, 3, 4]
12 -> [0, 3, 4]
13 -> [1, 2, 4]
14 -> [0, 2, 4]
15 -> [0, 1, 4]
16 -> [1, 2, 3]
17 -> [0, 2, 3]
18 -> [0, 1, 3]
19 -> [0, 1, 2]

答案 1 :(得分:2)

我们可以等同地考虑[(x,y) | x<-[0..n], y<-[0..x-1]]。这个清单有长度

n = x = 0 Σ n x = n·(n+1)/2

因此,我们可以得到一个给定的,最近的 n

n = n ·( n +1) = n 2 + n

n =-½±√(¼+ 2· n

特别是,对于给定的索引 i

n i - =⌊-½±√(¼+ 2· i )⌋

是最后一个完整三角形的x长度。因此,索引 i 位于行 n i - +1中。该三角形的面积为

n i - = n <子> I - ·(名词 <子> I - 1)< / SUP> / <子> 2

因此我们需要从 i 中减去以得到余数索引(在y方向上)。这就产生了定义

lowerTriangularTuple :: Int -> (Int,Int)
lowerTriangularTuple i = (nmin+1, i - (nmin*(nmin+1))`div`2)
 where nmin = floor $ -1/2 + sqrt(1/4 + 2 * fromIntegral i)

示例:

GHCi> lowerTriangularTuple <$> [0..30]
[(1,0),(2,0),(2,1),(3,0),(3,1),(3,2),(4,0),(4,1),(4,2),(4,3),(5,0),(5,1),(5,2),(5,3),(5,4),(6,0),(6,1),(6,2),(6,3),(6,4),(6,5),(7,0),(7,1),(7,2),(7,3),(7,4),(7,5),(7,6),(8,0),(8,1),(8,2)]