4

I'm trying to generate 10 random times within a range of two times, and there is a condition that the times generated cannot have less than 30 minutes between them. So, if i Start at 10:00am and end at 05:00pm, the times between these must be a least 30 minutes between them.

I already can get the random times, but don't know how to put the condition there, any ideas?

public LocalTime between(LocalTime startTime, LocalTime endTime) {
    int startSeconds = startTime.toSecondOfDay();
    int endSeconds = endTime.toSecondOfDay();
    int randomTime = ThreadLocalRandom
      .current()
      .nextInt(startSeconds, endSeconds);

    return LocalTime.ofSecondOfDay(randomTime);
}

i put this in a for loop to get 10 of them

Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
  • Sounds like you need to pass in the list of already generated times, and regenerate the `randomTime` if the any of the `LocalTime`'s in the list are within 30 minutes. – Orin Nov 05 '19 at 19:55
  • if you you want each (random) time to be beyond this range, then you have to memorize (at least/most) 9 of them... reconsider your algorithm, and plz define "random" more precisely (10 random time points within 10 hours...with this restriction, that's quite "narrow", ..you can use it to your/time/space/complexity advantage ...looking at your problem/task, i think more of a "random wheel" ...and a "moving" cursor/"slices"..) – xerx593 Nov 05 '19 at 19:55

3 Answers3

5

For a good random distribution: Out of the 7 hours between your start of 10:00 and your end of 17:00 (on a 24 hour clock, “military hours”), 4 hours 30 minutes are already reserved for your minimal gaps (9 gaps @ 30 minutes minimum). So subtract 4:30 from 7, this gives 2 hours 30 minutes of freedom.

  1. Generate 10 random times within 2 hours 30 minutes, for example the way you already do.
  2. Sort them chronologically.
  3. Add 0 minutes to the first time, 30 minutes to the next, 1 hour to the third, etc. So you will be adding 4 hours 30 minutes to the last time. This will make sure that the gaps become at least 30 minutes each and that the last time is still within the 17:00 end time.
Zoe
  • 27,060
  • 21
  • 118
  • 148
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

You can use isBefore in LocalTime, so check startTime+30 Min is before result and result is before endTime-30 Min

LocalTime result = LocalTime.ofSecondOfDay(randomTime);   

if (startTime.plusMinutes(30).isBefore(result) && result.isBefore(endTime.minusMinutes(30))) {
    return result;
}

Probably you can use while loop to loop until it get the valid result

while(true) {

  LocalTime result = LocalTime.ofSecondOfDay(ThreadLocalRandom. current().nextInt(startSeconds, endSeconds));   

if (startTime.plusMinutes(30).isBefore(result) && result.isBefore(endTime.minusMinutes(30))) {
    return result;
    }
  }
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
0

You can not generate truly random numbers with computers, you always have to have some strategy. And if your numbers are truly random then, they can not be aware of each other. So, you can not generate truly random time 30 minutes apart separately. You have to generate them all together. You have to find a minimum distance. And start time and end time must have enough distance to generate the number of random times you want.

You can generate any number of random times by the following method in any given range if they have enough distance -


public List<LocalTime> generateRandomTimes(LocalTime startTime, LocalTime endTime, int n) {

    if (n < 0) {
        throw new RuntimeException("Must be greater than zero");
    }

    List<LocalTime> localTimeList = new ArrayList<>();

    int startSeconds = startTime.toSecondOfDay();
    int endSeconds = endTime.toSecondOfDay();

    int minimumDistance = LocalTime.of(0, 30).toSecondOfDay();
    int standardDistance = (endSeconds - startSeconds) / n;

    if (standardDistance <= minimumDistance) {
        throw new RuntimeException("Not enough time distance to generate the required number of random times");
    }

    int randomRange = (endSeconds - (n * minimumDistance)) / n;

    for (int i = 1; i <= 10; i++) {
        int nextInt = ThreadLocalRandom
                .current()
                .nextInt(startSeconds, startSeconds + randomRange);

        LocalTime time = LocalTime.ofSecondOfDay(nextInt);
        localTimeList.add(time);

        startSeconds = nextInt + minimumDistance;
    }

    return localTimeList;
}