I think I found another way, that gives the pairs in lexicographic order. Note that here i > j
instead of i < j
.
Basically the algorithm consists of the two expressions:
i = floor((1 + sqrt(1 + 8*k))/2)
j = k - i*(i - 1)/2
that give i,j
as functions of k
. Here k
is a zero-based index.
Pros: Gives the pairs in lexicographic order.
Cons: Relies on floating-point arithmetic.
Rationale:
We want to achieve the mapping in the following table:
k -> (i,j)
0 -> (1,0)
1 -> (2,0)
2 -> (2,1)
3 -> (3,0)
4 -> (3,1)
5 -> (3,2)
....
We start by considering the inverse mapping (i,j) -> k
. It isn't hard to realize that:
k = i*(i-1)/2 + j
Since j < i
, it follows that the value of k
corresponding to all pairs (i,j)
with fixed i
satisfies:
i*(i-1)/2 <= k < i*(i+1)/2
Therefore, given k
, i=f(k)
returns the largest integer i
such that i*(i-1)/2 <= k
. After some algebra:
i = f(k) = floor((1 + sqrt(1 + 8*k))/2)
After we have found the value i
, j
is trivially given by
j = k - i*(i-1)/2