Randomly Choose from list but meet conditions
Here's a way that constructs a set of candidates by sorting the list and then breaking it into runs of consecutive elements and only keeping elements with enough successors to be viable. This is probably a good approach if you are going to be making multiple draws.
RandomSeed[1337];
test = RandomInteger[{0, 99}, 95]
(* {37, 84, 80, 98, 26, 32, 51, 65, 19, 33, 10, 88, 25, 13,
77, 68, 20, 39, 27, 83, 89, 75, 78, 87, 22, 58, 94, 49,
70, 73, 60, 44, 59, 86, 30, 12, 90, 5, 55, 63, 38, 35,
72, 81, 31, 36, 29, 93, 95, 8, 34, 15, 9, 42, 52, 50,
48, 4, 92, 71, 56, 2, 69, 54, 74, 91, 45, 64, 0, 82,
96, 85, 16, 6, 7} *)
runs = Split[Sort[test], Subtract /* EqualTo[-1]];
Only runs of length $ > 3 $ will contain elements $ a $ such that $ a + 1 $, $ a + 2 $, and $ a + 3 $ are present:
longRuns = Select[runs, Length /* GreaterThan[3]];
Drop
elements that don't have enough successors and flatten.
candidates = Flatten[Drop[#, -3] & /@ longRuns]
(* {4, 5, 6, 7, 29, 30, 31, 32, 33, 34, 35, 36, 48, 49, 68,
69, 70, 71, 72, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
90, 91, 92, 93} *)
Now you can make random draws.
RandomChoice[candidates, 10]
(* {34, 85, 89, 90, 4, 81, 83, 29, 93, 85} *)
Here is a procedural approach that does not require the list to be sorted.
I will first make some test data:
testlist = RandomSample[Range[0, 99], 50];
Then define a selector function:
testlist = RandomSample[Range[0, 99], 50];
ClearAll[selector]
selector[list_] :=
TimeConstrained[
Module[{choice},
While[!
ContainsAll[list, (choice = RandomChoice[list]) + {0, 1, 2}]];
choice
],
0.5,
"None found"
]
selector[testlist]
Wrapping the function in TimeConstrained
ensures that, in case there are no such elements, the function won't get stuck in an endless loop. The return value could be the default ($Aborted
), or it could be modified to taste as shown above. For example:
selector[Range[0, 99, 2]]
(* Out: None found *)
To create some data for testing we get even numbers <100 and insert one odd number:
d = Table[i, {i, 0, 99, 2}];
d = Insert[d, 33, 18];
Now we can pick out a sequence of 3 integers in a row by:
SequenceCases[d, {x_, y_, z_} /; z == (y + 1) == x + 2, 1]
(* {{32, 33, 34}} *)
If you only want the first number, you would say:
SequenceCases[d, {x_, y_, z_} /; z == (y + 1) == x + 2 -> x, 1][[1]]
(* 32 *)