15,848,904 members
See more:
Select x elements from list of length n. It cannot be first and last element, and all selected elements must not be adjacent to each other.

If we assume a list of length 10 from 0 to 9, feasible examples:
1 5 8 (x = 3)
2 4 (x = 2)
1 3 5 8 (x = 4)

Examples that do not meet the requirements:
0 9 (x = 2)
1 2 3 (x = 3)
3 5 6 9 (x = 4)

There is a certain maximum value of x and going above that these requirements can't be met, but this is something that I can handle on my own.

I know that you can for example do:
C#
var selected = list.OrderBy(x => Guid.NewGuid()).Take(x).ToList();

But this won't meet any of these constraints. You can remove first and last elements before ordering, but still second requirement is not met.

What I have tried:

Posted
Updated 12-Sep-22 2:34am

Solution 1

First, generate a collection of indices that match the criteria:
The way I'd do it is to create a collection containing all valid indexes at the start (i.e. 0 to N-2 to exclude the first and last elements) - Enumerable.Range will do that for you.So if N = 8, and x = 3 then
N = 8: 1 2 3 4 5 6
Then generate a random index in that collection, and remove it and the values one larger and one smaller (if present)
i = 3:
index in original table = 4
1 2 6

Generate a random index again and repeat until x has been met or you can't get another value.

At the end, you can use the values to index into your original collection.
Try it on paper and you'll see what I mean.

CPallini 12-Sep-22 7:39am
5.
Member 15047625 12-Sep-22 7:57am
Ok thats smart. I have already did it on my own but it's definitely suboptimal - iterate through collection (except first and last element) and pick them with certain probability. Once selected, skip next adjacent element. If enough items have been selected exit, if not enough finish the job and get the rest by brute force without randomness (while respecting constraints).
OriginalGriff 12-Sep-22 8:24am
Except your question specifically requires randomness! :D