0

I want to select random elements from a list without the possibility of repeating the same element twice in a row. I want to have a guaranteed amount of other elements between choosing the same element again. Additionally it has to be impossible to 100% predict what the next choice will be.

My current solution is to select elements at random until I selected one third of the total elements. Then I randomly select half of the the other elements to get another third. After that I add the first third back to the remaining elements and repeat the process.

This way I have a guaranteed distance of 1/3 of the total elements before repeating an element. But, I would like to have an even larger spacing. Is there any way to achieve this without making the choice predictable?

Peter O.
  • 32,158
  • 14
  • 82
  • 96
  • Which programming language are you using? – Asocia Jun 15 '20 at 00:21
  • I am using Pascal – Currywurst Jun 15 '20 at 00:49
  • How many values are you talking about? Are they stored in an array, in multiple arrays, or in some other structure? You really need to provide some details. – pjs Jun 15 '20 at 01:05
  • Currently I have a few hundred sentences stored inside a txt document. Selecting one of these isnt the problem. My problem is to decide the pattern of how to select these elements. – Currywurst Jun 15 '20 at 01:22

1 Answers1

0

I can't help you with Pascal, I don't have a copy and haven't used it for over 30 years so I don't know what libraries you might have access to.

With that out of the way, the task is fairly straightforward if you have (or can fake) a queue data structure so you can store things in First-In-First-Out order.

  • Shuffle the original array, then slice the desired "spacing" number of elements off the end of it.
  • Select an element at random from the N - spacing items in the array by randomly generating an index.
  • Do whatever you want with that item, but then append it to the queue.
  • Pop the first element off the queue and store it in the location of the item you just selected/used.

Voila! Items that have recently been used are stored in the queue until they get to the front, then they are recycled into the set from which you are randomizing. Since they are out of circulation for the length of the queue, the spacing is guaranteed.

Here it is in Ruby, which is close to being pseudo-code. I've also annotated the heck out of it.

ary = (1..10).to_a   # create an array "ary" containing the numbers 1 to 10
ary.shuffle!         # shuffle the array
spacing = ary.length / 3  # set the desired spacing as fraction of ary

# Now we'll slice the last "spacing" elements off into a queue,
#   starting at location ary.length - spacing
queue = ary.slice!(ary.length - spacing, spacing)
p ary, queue         # print the array and queue to show the random splitting

# Now we're set up with "spacing" random elements (from the shuffling)
# in a queue, and the rest still in "ary"
20.times do  # do the following 20 times for demo purposes
  index = rand(ary.length)    # Choose a random index in "ary",
  print ary[index]            # print it out,
  print ' '                   # and print a space after it.
  queue << ary[index]         # Now append it to the queue
  ary[index] = queue.shift    # and replace that location with the first element popped from the queue
end
puts    # put a new-line at the end of the printed values

which produces, for example:

[7, 2, 3, 8, 6, 10, 5]
[9, 1, 4]
5 7 8 3 5 2 9 4 1 7 3 6 1 5 3 2 4 6 1 7 

The first line is the shuffled array after slicing, the second line is the queue of sliced values, and the third line is the result of 20 iterations of the algorithm. Note that no element occurs within 3 of its prior usage.

pjs
  • 18,696
  • 4
  • 27
  • 56
  • @Currywurst Glad that works for you, and sorry I couldn't do it in your preferred language. – pjs Jun 15 '20 at 22:40