Yes, when initialized with "size=5" the numbers in the output must be precisely 1,2,3,4,5 but in random looking order.
And I don't want to store the whole sequence. I want to say gimmeTheNumberAtPosition(x) and it return just that number.
https://en.wikipedia.org/wiki/Fisher–Yates_shuffle
ETA: As you don't want to store the permutation, you might want to pick a number randomly from 1 to n!, and then generate the permutation on the fly up to the desired element, using the techniques outlined here:
https://stackoverflow.com/questions/29236556/how-can-i-calcu...
In other words, good old Fisher Yates, storing the resulting permutation, and a simple lookup is probably the way to go.
Edit: yes, here is an example (in the comments) of how biased this is: https://stackoverflow.com/a/18650169/923847
https://www.robweir.com/blog/2010/02/microsoft-random-browse...
The Fisher–Yates shuffle is the right way to shuffle an array in an unbiased way.
This is simple and fast, but is not secure at all. You can solve for a, b by solving the linear congruence. It also does not generate every permutation of `n`. For n = 5, only 20 sequences can be found out of 5! = 120.
Since the "randomness" of the permutation is not that great, I was looking for something better, but could not find anything. The closest I got was https://en.wikipedia.org/wiki/Xorshift#xoshiro_and_xoroshiro which only works for powers of two. A workaround would be to choose the next larger power of two and reject all random values which are smaller than `n`, but that introduces unpredictable latency and destroys the cool jump-ahead feature.
For example, with n = 5: Let a = 3 and b = 2. x = [0, 1, 2, 3, 4], a * x = [0, 3, 6, 9, 12], a * x + b = [2, 5, 8, 11, 14], a * x + b mod n = [2, 0, 3, 1, 4]
For size=1, all parameters are 1, and only result is 1.
For size 2, r can be 1 or 2, naming the permutations [1,2];[2,1] - and eg: rand_at(n=2,r=2,i=2) would return 2, but i=1, would return 2.
I'm not sure how I'd implement this - I suppose it might be possible to generate a predictable "walk" based on n/r/i?
But for sizes less than, say, a million i would think that a shuffled array would be easier?
r would need to be in the range 1..n!