Reputation: 26788
I have a line. It starts with two indexes, call them 0 and 1, at the outermost points. At any point I can create a new point which bisects two other ones (there must not already be a point between them). However when this happens the indexes need to increment. For example, here's a potential series of steps to achieve N=5 since there are indexes in the result.
(graph) (split between) (iteration #)
< ============================ >
0 1 0,1 0
0 1 2 1,2 1
0 1 2 3 0,1 2
0 1 2 3 4
I have two questions:
This is an issue I've encountered when developing a video game.
Upvotes: 0
Views: 238
Reputation: 7750
I agree with jdehesa in that what you are doing does have its similarities with a binary tree. I would recommend looking in using that data structure if you can, since it is highly structured, well-defined, and many great algorithms exist for working with them.
Additionally, as mentioned in the comment section above, a linked list would also be a nice option, since you are adding in a lot of elements. A normal array (which is contiguous in memory) will require you to move many elements over and over again as you insert additional elements, which is slow. A linked list would allow you to add your element anywhere in memory, and then just update a few pointers in the linked list on both sides of where you want to insert it, and be done. No moving things around.
However, if you really just want to put together a working solution using array and aren't concerned with using other data structures, here is the math for the indexing you requested:
Each pair can be listed as (a, b), and we can quickly see b = a + 1. Thus, if you find a, you know b. To get these, you'll need two loops:
iteration := 0
i := 0
while iteration < desired_iterations
for j = (2 ^ i) - 1; j >= 0 && iteration < desired_iterations; j--
print j, j + 1
iteration++
i++
Where ^ is the exponentiation operator. What we do is find the second to last element in the list (2^i)-1 and count backwards, listing off the indices. We then increment "i" to signify that we've now doubled our array size, and then repeat again. If at any point we research our desired number of iterations, we break out of both loops because we're finished.
Upvotes: 1
Reputation: 59741
I'm not sure if this is the kind of answer you are looking for, but I see this as a binary tree structure. Every tree node contains its own label and its left and right labels. The root of the tree (level 0) would be (2, 0, 1)
(split 2
with 0
on the left and 1
and the right). Every node would be split into two children. The algorithm would go something like this:
For example, at iteration 5 you would have something like this:
Level 0: (2, 0, 1)
/ \
/ \
/ \
Level 1: (3, 0, 2) (4, 2, 1)
/
/
Level 2: (5, 0, 3)
Now, to reconstruct the current split, you would do the following:
For the previous case, you would have:
S = [0]
(5, 0, 3) -> S = [0, 5, 3]
(3, 0, 2) -> S = [0, 5, 3, 2]
(4, 2, 1) -> S = [0, 5, 3, 2, 4, 1]
(2, 0, 1) -> S = [0, 5, 3, 2, 4, 1]
So the complete split would be [0, 5, 3, 2, 4, 1]
. The split would be perfectly balanced only when N = 2k for some positive integer k. Of course, you can annotate the tree nodes with additional "distance" information if you need to keep track of something like that.
Upvotes: 1