10

I have an interval G, and a set of non-overlapping sub-intervals of various lengths s1, s2, ..., sn.

G |--------------------------------------------------------------// //-----------|
        s1 [---]                       s3 [------------------]
                    s2 [------]                                         sn [--]     

I'm looking for an algorithm for taking all of these sub-intervals and then placing them again on G randomly, such that they don't overlap. What is the best way to do this?

The easiest, most naive approach would be simply to randomly select starting positions for each subinterval, check for overlaps once all intervals are placed, and then start over if there are overlaps. This would probably be pretty fast if the sub-intervals provide sparse coverage of G, but increasingly inefficient as density increases.

A similar idea is to check for overlap as each sub-interval is placed. Similar concerns about efficiency though.

Is there any more clever way of handling this?

UPDATE

To clarify a couple of points:

  • It is the spacing of the sub-intervals that I would like randomly distributed.
  • The uniform distribution is probably the most appropriate concept of randomness in this case.
  • These are discrete (integer) closed intervals, not continuous.
Daniel Standage
  • 8,136
  • 19
  • 69
  • 116
  • 1
    I think you need to specify (1) what distribution you want, and (2) what exactly you want to be randomly distributed. The left sides of the sub-intervals, the right sides (as measured from the left), the gaps in between them? Once you specify them you can test for it formally. – user1666959 Nov 20 '15 at 16:57
  • Excellent question: it is the spacing of the sub-intervals (and accordingly the gaps between them) that I would like randomly (probably uniformly) distributed. – Daniel Standage Nov 20 '15 at 17:07
  • I'm stil missing something: the sum of the length of sub intervals is a number S. G-S is then the sum of all spaces. So you want N+1 random numbers (N-1 would separate the N intervals and you want one more on each end) drawn from the uniform distribution such that their sum is G-S. Right? Nice question. Would you mind telling where does it arise? – user1666959 Nov 21 '15 at 16:11

2 Answers2

9

I think okio's answer will give a biased distribution of the gaps (i.e. the first gaps will tend to be larger then later gaps.

However, I think a very similar approach should work better:

  1. Shrink all sn to zero length
  2. Choose random positions for each sn in lenG-lenS
  3. Expand sn back to their original lengths
Peter de Rivaz
  • 33,126
  • 4
  • 46
  • 75
  • 1
    With this route step#1 isn't needed, since step #3 randomizes them anyway. – Mark Peters Nov 20 '15 at 16:57
  • 1
    Really nice and simple solution, but I think you still need to randomise the order of the selection of positions. Imagine the edge case of lenG=lenS, where everyone will be on position 0. – biziclop Nov 20 '15 at 17:19
  • Unless, that is, it is a requirement for `s1` to come before `s2` and so on. – biziclop Nov 20 '15 at 17:26
  • I may just lay them out with random spacing between so that it is longer than the interval, then decrease whitespace until it fits. Add in some finagling magic so the last interval isn't always resting against the end of the main interval. – S. Buda Nov 20 '15 at 20:06
  • You should shrink the intervals to size 1, not 0, and and then select n distinct starting positions in [0, lenG - lenS + n) If order should be randomized, you then do a random shuffle before restoring the lengths. – rici Nov 21 '15 at 01:15
4

Something like this ?

lenG = length(G)
lenS = length(s1) + length(s2) + length(s3) + length(sn)

empty_place_available = lenG - lenS
current_position = 0;

sort sn randomly

loop for each sn
    rand = rand(0, empty_place_available)
    position[sn] = current_position + rand
    empty_place_available = empty_place_available - rand
    current_position = current_position + rand + length(sn)
ôkio
  • 1,772
  • 1
  • 15
  • 16