Pick a random number between 0 and n using a constant source of randomness

26

2

Task

Given a positive integer n less than 2^30 specified as input in any way you choose, your code should output a random integer between 0 and n, inclusive. The number you generate should be chosen uniformly at random. That is each value from 0 to n must occur with equal probability (see Rules and Caveats).

Rules and Caveats

Your code can assume that any random number generator built into your language or standard library that claims to be uniformly random is in fact uniform. That is you don't have to worry about the quality of the random source you are using. However,

  • You do have to establish that if the random source you are using is uniform then your code correctly outputs a uniform random integer from 0 to n.
  • Any arguments when calling a built in or library random function must be constant. That is they must be completely independent of the input value.
  • Your code may terminate with probability 1 rather than being guaranteed to terminate.

Notes

  • randInt(0,n) is not valid as it takes the input as an argument to a builtin or library function.
  • rand()%n will not give a uniform random number in general. As an example given by betseg, if intmax == 15 and n = 10, then you will be much more likely to get 0-5 than 6-10.
  • floor(randomfloat()*(n+1)) will also not give a uniform random number in general due to the finite number of different possible floating point values between 0 and 1.

user9206

Posted 2017-02-28T10:17:59.827

Reputation:

How are you going to confirm that the output is uniformly random? It may be that a given language / library will output uniformly random numbers, but manipulation could result in non-uniform output. (e.g. rng() provides 0-100, if n = 75, and function is rng()%75, then 0-25 will be more common...) – Baldrickk – 2017-03-01T16:12:00.540

1@Baldrickk By the wisdom of crowds :) We can only read the code and think about it. – None – 2017-03-01T16:13:00.483

The sad conclusion of asking the simplest possible probability-theory question: randomness and probability are very poorly understood. :( (And reading rules is hard, apparently.) – Martin Ender – 2017-03-01T22:11:45.063

This comes to mind: Random Number

– BgrWorker – 2017-03-02T09:05:54.147

Why did you accept the x86 answer when there are three shorter ones? – Dennis – 2017-03-30T16:30:50.100

May I point out that python defines random.uniform() as a + (b-a) * self.random(), So is floor(randomfloat()*(n+1)) valid???

– The Matt – 2018-07-10T01:36:25.857

Answers

25

x86 machines with rdrand instruction, 10 bytes

BITS 64

_try_again:

 rdrand eax
jnc _try_again

 cmp eax, edi
ja _try_again

 ret

machine code

0FC7F0 73FB 39F8 77F7 C3

The input is in the register rdi and the output in rax.
This respects the SYS V AMD64 ABI so the code effectively implement a C function

unsigned int foo(unsigned int max); 

with 32-bit ints.

The instruction rdrand is described by Intel

RDRAND returns random numbers that are supplied by a cryptographically secure, deterministic random bit generator DRBG. The DRBG is designed to meet the NIST SP 800-90A standard.

Dealing with CSRNG it is implicit that the distribution is uniform, anyway, quoting the NIST SP 800-90A:

A random number is an instance of an unbiased random variable, that is, the output produced by a uniformly distributed random process.


The procedure generates a random number and if it is non-strictly greater than the input it is returned.
Otherwise, the process is reiterated.

Since eax is 32-bit, rdrand returns a number between 0 and 232-1, so for every n in [0, 232-1] the number of expected iterations is 232/(n+1) which is defined for all n in [0, 230).

Margaret Bloom

Posted 2017-02-28T10:17:59.827

Reputation: 1 946

Brilliantly low level. Thank you. – None – 2017-02-28T15:22:41.743

What's the jnc for? – l4m2 – 2018-05-27T17:04:37.567

@l4m2 rdrand sets the CF iif the data returned is valid. Data may be invalid because too many requests drained the entropy pool. See the manual entry for rdrand and this.

– Margaret Bloom – 2018-05-27T20:30:08.133

20

Jelly, 7 6 bytes

⁴!!X%‘

Thanks to @JonathanAllan for golfing off 1 byte!

Cannot be run on TIO because (16!)! is a huge number.

How it works

⁴!!X%‘  Main link. Argument: n

⁴       Set the return value to 16.
 !!     Compute (16!)!.
   X    Pseudo-randomly choose an integer between 1 and (16!)!.
        Since (16!)! is evenly divisible by any k ≤ 2**30, it is evenly divisible
        by n+1.
    %‘  Take the result modulo n+1.

Dennis

Posted 2017-02-28T10:17:59.827

Reputation: 196 637

This is a fixed version of my deleted answer, same idea. Although I did have an unnecessary exponentiation. – orlp – 2017-02-28T14:10:52.953

Sorry, I didn't look at it before posting. – Dennis – 2017-02-28T14:19:02.370

Oh it doesn't matter, I wasn't planning fixing it anyway. I'm too uncomfortable with Jelly to really play around with it. – orlp – 2017-02-28T14:26:08.627

1"Sir I don't know why you're mad. The algorithm is constant time. That's a good thing, right? Why is security and HR outside the door?" – corsiKa – 2017-03-02T03:31:49.193

@JonathanAllan Ugh, double factorial notation is weird... Thanks for the edit. – Dennis – 2017-03-02T12:37:00.880

1Agreed. Bit of a difference between an 8 digit number and a 417 quintillion digit number :p – Jonathan Allan – 2017-03-02T12:37:53.503

11

Mathematica, 29 bytes

Based on Dennis's Jelly answer.

RandomInteger[2*^9!-1]~Mod~#&

I wouldn't recommend actually running this. 2e9! is a pretty big number...

It turns out to be shortest to generate a huge number that is divisible by all possible inputs and the map the result to the required range with a simple modulo.

Rejection Sampling, 34 bytes

My old approach that led to somewhat more interesting code:

13!//.x_/;x>#:>RandomInteger[13!]&

Basic rejection sampling. We initialise the output to 13! (which is larger than the maximum input 230) and then repeatedly replace it with a random integer between 0 and 13! as long as the value is bigger than the input.

Martin Ender

Posted 2017-02-28T10:17:59.827

Reputation: 184 808

1Do you mean "smaller than or equal to the input" ? – None – 2017-02-28T10:25:52.730

1@Lembik No. We want to regenerate the value as long as it doesn't fall into the desired range. – Martin Ender – 2017-02-28T10:26:29.937

Oh I see. For some reason I thought we were repeatedly sampling from the desired range. Thanks. – None – 2017-02-28T10:26:51.680

1Remind me to add a time limit next time :) – None – 2017-03-01T15:38:47.207

9

Brachylog, 9 bytes

≥.∧13ḟṙ|↰

Try it online!

This uses 13! like in Martin Ender's answer (13ḟ is one byte less than 2^₃₀).

is implemented using random_between/3, which, when digging its source, uses random_float/0 which is linked to random/1 which uses the Mersenne Twister algorithm which is uniform for our purposes.

Explanation

≥.           Input ≥ Output
  ∧          And
   13ḟṙ      Output = rand(0, 13!)
       |     Else
        ↰    Call recursively with the same input

Fatalize

Posted 2017-02-28T10:17:59.827

Reputation: 32 976

7

Python, 61 bytes

from random import*
lambda n,x=2.**30:int(randrange(x)*-~n/x)

Edit: Updated to avoid forbidden form

Edit2: Saved 2 bytes, thanks @JonathanAllan

Edit3: Paid 2 bytes for a fully functional solution - thanks again @JonathanAllan

Edit4: Removed f=, saving 2 bytes

Edit5: Saved 1 more byte thanks to @JonathanAllan

Edit6: Saved 2 more bytes thanks to @JonathanAllan

By now, git blame would point at me for the bad things, and JonathanAllan for the stuff that helps.

Edit7: When it rains, it pours - another 2 bytes

Edit8: And another 2 bytes

iwaseatenbyagrue

Posted 2017-02-28T10:17:59.827

Reputation: 231

1This wont ever output n, but you can save two bytes when you fix that by using from random import* and dropping the r.. – Jonathan Allan – 2017-02-28T13:28:39.660

Thanks for that - I guess I could spend those two bytes you saved me on making it possible to output n too (e.g. (1+n*1.0)/2**30) – iwaseatenbyagrue – 2017-02-28T13:33:49.873

1Yes, you can use the "tadpole operator" to avoid the otherwise necessary parentheses, so ...*(-~n*1.0/2**30)) rather than ...*((n+1)*1.0/2**30)) – Jonathan Allan – 2017-02-28T13:36:38.760

Also you do not need to count the f= since you are not using recursion (unnamed functions are fine) – Jonathan Allan – 2017-02-28T13:39:25.137

1Really? Sweet! Do you have some long-standing grudge against the number 70? Thanks a lot for your help – iwaseatenbyagrue – 2017-02-28T13:42:58.430

Oooh, one more - you can remove the 0 from 1.0 :D – Jonathan Allan – 2017-02-28T13:47:03.270

...you can just use randrange(2**30). – Jonathan Allan – 2017-02-28T13:59:45.103

1In fact randrange seems to accept a float, so lambda n,x=2.**30:int(randrange(x)*-~n/x) saves another two [edit...] four! – Jonathan Allan – 2017-02-28T14:02:46.613

Jonathan, really my deepest thanks – iwaseatenbyagrue – 2017-02-28T14:06:07.397

1^ another two in there with parentheses removal. Just goes to show your multiplication was the way to go! – Jonathan Allan – 2017-02-28T14:08:46.820

1

Oh, unfortunately this actually has a bias to 0 due to the way it buckets, imperceivable as is, to see it change 2**30 to something small like 10. (e.g. this)

– Jonathan Allan – 2017-02-28T14:41:50.807

1Bugger - related to the fact things are being rounded down when run through int(), I guess. And I have to thank you for taking it that deep.... Back to the drawing board/source of caffeine. – iwaseatenbyagrue – 2017-02-28T14:54:25.997

@NoOneIsHere thanks for your edits - and fixing the actual code.

– iwaseatenbyagrue – 2017-03-02T11:48:44.000

7

Prolog (SWI), 38 bytes

X*Y:-Z is 2^31,random(0,Z,Y),Y=<X;X*Y.

Works by rejection sampling.

Generate a random number between 0 and 2^31-1 = 2147483647 until one less than or equal to the input has been found.

I feel as if I should be able to use a cut instead of the else, but I can't see how.

Emigna

Posted 2017-02-28T10:17:59.827

Reputation: 50 798

1You could avoid the else using repeat, but it ends up being 3 bytes longer… I'm not sure if there is a shorter way of having infinite choice points than repeat. – Fatalize – 2017-02-28T14:17:11.483

@Fatalize: Yeah I tried repeat as well. I had a memory of using something like ,!. to force a backtrack, but either I'm remembering it wrong or it's not applicable to this solution. – Emigna – 2017-02-28T14:22:25.243

7

Labyrinth, 63 bytes

 ?
 #00}__""*_
 ;    #"  _
{-{=  } "><)
!{ : ;"({ +
@  }}:  >`#

(Thanks to @MartinEnder for help with some heavy golfing here.)

Labyrinth is a 2D language, and its only source of randomness is in a situation like the following:

   x
  "<)
 " "
 " "

Assume the instruction pointer is on the x and moving downwards. It next lands on the <, which if the top of stack is 0 (which is always the case in the actual program above) shifts the current row left by 1:

   "
 "<)
 " "
 " "

The instruction pointer is now on the < moving downwards. At a junction, Labyrinth turns based on the top of stack - negative is turn left, positive is turn right and zero is move forward. If the top of stack is still zero at this point, we can't move forward or backward since there's no path, so Labyrinth will randomise between turning left or turning right with equal probability.

Essentially what the program above does is use the randomness feature to generate 100-bit numbers (100 specified by #00 here) and continue looping until it generates a number <= n.

For testing, it'll probably help to use #0" instead for 10-bit numbers, with the " being a no-op path. Try it online!

Rough explanation:

 ?            <--- ? is input and starting point
 #0"}__""*_   <--- * here: first run is *0, after that is *2 to double
 ;    #"  _
{-{=  } "><)  <--- Randomness section, +0 or +1 depending on path.
!{ : ;"({ +        After <, the >s reset the row for the next inner loop.
@  }}:  >`#

 ^    ^
 |    |
 |    The " junction in this column checks whether the
 |    100-bit number has been generated, and if not then
 |    continue by turning right into }.
 |
 Minus sign junction here checks whether the generated number <= n.
 If so, head into the output area (! is output as num, @ is terminate).
 Otherwise, head up and do the outer loop all over again.

Sp3000

Posted 2017-02-28T10:17:59.827

Reputation: 58 729

6

Python 2, 61 bytes

from random import*
lambda n:map(randrange,range(1,2**31))[n]

Pseudo-randomly chooses integers between 0 and k for all values of k between 0 and 231 - 2, then takes the integer corresponding to k = n.

Dennis

Posted 2017-02-28T10:17:59.827

Reputation: 196 637

5

Batch, 64 bytes

@set/ar=%random%*32768+%random%
@if %r% gtr %1 %0 %1
@echo %r%

%random% only gives 15 bits of randomness, so I have to combine two random numbers. Loops until the random value lies within the desired range, so slow for low n; 98 bytes for a faster version:

@set/a"n=%1+1,m=~(3<<30)/n*n,r=%random%*32768+%random%
@if %r% geq %m% %0 %1
@cmd/cset/a%r%%%%n%

Neil

Posted 2017-02-28T10:17:59.827

Reputation: 95 035

The code may be slow but your answer was fast! – None – 2017-02-28T10:22:52.443

3@Lembik I had the answer ready to go in your deleted question... – Neil – 2017-02-28T10:25:50.417

Won't this echo the desired number first, and then all other numbers which turned to be larger than n? – Erik the Outgolfer – 2017-02-28T12:01:52.547

@EriktheOutgolfer No; unless you use call, invoking a batch script terminates the current script. – Neil – 2017-02-28T16:03:46.407

5

MATL, 12 bytes

Thanks to @AdmBorkBork and to @Suever for telling me how to disable TIO cache.

`30WYrqG>}2M

Try it online!.

This uses a rejection method: generate a random integer from 0 to 2^30-1, and repeat while it exceeds the input n. This is guaranteed to terminate with probability 1, but the average number of iterations is 2^30/n, and so it takes very long for n significantly smaller than 2^30.

`         % Do...while
  30W     %   Push 2^30
  Yr      %   Random integer from 1 to 2^30
  q       %   Subtract 1
  G>      %   Does it exceed the input? If so: next iteration. Else: exit
}         % Finally (execute right before exiting the loop)
  2M      %   Push the last generated integer
          % End (implicit). Display (implicit)

Luis Mendo

Posted 2017-02-28T10:17:59.827

Reputation: 87 464

4

Jelly, 9 bytes

⁴!Ẋ’>Ðḟ⁸Ṫ

Try it online! - code above wont run on TIO since a range of size 16! must be built first (not to mention the fact that they then need to be shuffled and then filtered!), so this is the same thing on a much smaller scale, repeated 30 times for an input of 3 with a bound of 10.

How?

⁴!Ẋ’>Ðḟ⁸Ṫ - Main link: n
⁴         - 16
 !        - factorial: 20922789888000
  Ẋ       - shuffle random: builds a list of the integers 1 through to 16! inclusive and
          - returns a random permutation via Python's random.shuffle (pretty resource hungry)
   ’      - decrement (vectorises - a whole pass of this huge list!)
     Ðḟ   - filter out if: (yep, yet another pass of this huge list!)
    >     -     greater than
       ⁸  -     left argument, n
        Ṫ - tail: return the rightmost remaining entry.

Note: it would be over a thousand time more efficient for the same byte-count if ȷ⁵ would do what one would naively expect and return ten to the ten, but that is not the case since the is not evaluated as a literal ten to be used by the number literal ȷ... but rather two separate literals are parsed, ȷ with it's default exponent of three yielding one thousand, and yielding ten.

Jonathan Allan

Posted 2017-02-28T10:17:59.827

Reputation: 67 804

Huh, thats 9 characters, but 22 bytes – Kristoffer Sall-Storgaard – 2017-03-02T15:17:41.200

@KristofferSall-Storgaard Each character is one of the 256 bytes in Jelly's code page, I forgot to make the word bytes a link like I usually do.

– Jonathan Allan – 2017-03-02T15:22:19.500

1year, I looked it up and found out the same – Kristoffer Sall-Storgaard – 2017-03-02T15:29:37.117

4

JavaScript (ES6), 55 54 bytes

f=(n,m=1)=>m>n?(x=Math.random()*m|0)>n?f(n):x:f(n,m*2)

Generates integers in the range [0 ... 2k - 1], where k is the smallest integer such that 2k is greater than n. Repeats until the result falls into [0 ... n].

Why?

This is based on the following assumptions:

  • Internally, the pseudo-random integer values generated by the JS engine to feed Math.random() are uniform over any interval [0 ... 2k-1] (with k < 32).

  • Once multiplied by an exact power of 2, the IEEE 754 float values returned by Math.random() are still uniform over such intervals.

If anyone can confirm or refute these hypotheses, please let me know in the comments.

Demo

Generates 1 million values in [0 ... 2] and displays the outcome statistics.

f=(n,m=1)=>m>n?(x=Math.random()*m|0)>n?f(n):x:f(n,m*2)

for(i = 0, stat = []; i < 1000000; i++) {
  r = f(2);
  stat[r] = (stat[r] || 0) + 1;
}
console.log(stat.join` `)

Arnauld

Posted 2017-02-28T10:17:59.827

Reputation: 111 334

Math.floor(Math.random()*(n+1)) produces a no less uniformly distributed results for me, so it would be nice to see if there is any realistic N < 2^30, which will produce any distribution anomalies at all. – zeppelin – 2017-03-01T16:23:40.677

1@zeppelin you'd need way too many trial runs to pinpoint any anomalies since a random float in that range will have one of 2^53 values which will be distributed as evenly as possible over the 2^30 outcomes. So even for large numbers in the range, the error will be something like 1 in 2^23 which means you'd need a ridiculous number of trials. You'll probably want a few more orders of magnitude than the number of initial samples (2^53). Nevertheless, it can't be perfectly uniform if the multiplier doesn't evenly divide the number of samples which is why Arnauld uses a power of two. – Martin Ender – 2017-03-01T21:52:28.017

4

Bash (+coreutils), 44 bytes

/dev/urandom based solution

od -w4 -vtu4</d*/ur*|awk '($0=$2)<='$1|sed q

Will read unsigned 32 bit integers from /dev/urandom, and filter them out with awk until it finds one within a given range, then sed q will abort the pipe.

zeppelin

Posted 2017-02-28T10:17:59.827

Reputation: 7 884

Hooray for bash :) – None – 2017-02-28T15:22:20.567

4

Haskell, 70 bytes

import System.Random
g n=head.filter(<=n).randomRs(0,2^30)<$>getStdGen

Not a very efficient algorithm but it works. It generates an infinite list of integers (or floats if needed, because of Haskell's type system) bounded by [0,2^30] and takes the first one less than or equal to n. For small n this can take a long time. The random numbers should be uniformly distributed, as specified in the documentation for randomR so all numbers in the interval [0,2^30] should have the same probability (1/(2^30+1)) therefore all the numbers in [0,n] have the same probability.

Alternate Version:

import System.Random
g n=head.filter(<=n).map abs.randoms<$>getStdGen

This version is terrible but it saves a whole byte. randoms uses an arbitrary range defined by the type to generate an infinite list of numbers. This may include negatives so we need to map it with abs to force them positive (or zero). This is extremely slow for any values of n that aren't absurdly large. EDIT: I realized later that this version isn't uniformly distributed because the probability of getting 0 is worse than the other numbers due to the use of abs. To produce some number m the generator could produce m or -m but in the case of 0 only 0 itself will work, therefore its probability is half of the other numbers.

user1472751

Posted 2017-02-28T10:17:59.827

Reputation: 1 511

Hooray for Haskell (too)! – None – 2017-02-28T15:34:58.767

4

JDK 9 on jshell, 75 59 bytes

n->(new Random()).ints(0,1<<30).dropWhile(x->x>n).findAny()

Usage

((IntFunction)(n->(new Random()).ints(0,1<<30).dropWhile(x->x>n).findAny())).apply(<n>)
  • -16 bytes: Thanks Jakob!
  • Assumes that we consider jshell to be a valid runtime environment.
  • jshell itself, as a runtime environment, doesn't require explicit imports for core libraries and doesn't require semicolons.
  • Returns an OptionalInt. Rules don't specify that return type must be a primitive and I'm considering an OptionalInt to be a valid representation of the result.

Pete Terlep

Posted 2017-02-28T10:17:59.827

Reputation: 41

1Thanks to @kevin-cruijssen for the inspiration. My first code golf! – Pete Terlep – 2017-03-01T23:37:17.000

Whether or not boxed output is accepted is different from whether an Optional is accepted. I would confirm with the poster if I were you. Also, no need to count the whole assignment; just the lambda expression is sufficient. – Jakob – 2017-08-09T13:48:42.423

1You can save 4 bytes by removing parentheses around lambda parameter n and new Random(). – Jakob – 2017-08-09T13:49:36.140

3

PHP, 30 bytes

    while($argn<$n=rand());echo$n;

Run with echo <N> | php -Rn '<code>'.

picks a random number between 0 and getrandmax() (2**31-1 on my 64 bit machine);
repeats while that is larger than the input.

This may take a while ... my AMD C-50 (1 GHz) needed between 0.3 and 130 seconds for N=15.

A faster way for average N (46 bytes):

for(;++$i<$x=1+$argn;)$n+=rand()%$x;echo$n%$x;

or

for(;++$i<$x=1+$argn;$n%=$x)$n+=rand();echo$n;

takes N+1 random integers, sums them up and takes the modulo with N+1.
The C-50 needs approx. 8 seconds for 1 million runs.

An invalid solution for 19 bytes:

echo rand(0,$argn);

Titus

Posted 2017-02-28T10:17:59.827

Reputation: 13 814

3

Python 2, 72 69 bytes

-3 bytes thanks to xnor (override the id built-in as a variable)

from random import*
n=input()
while id>n:id=randrange(2**30)
print id

Try it online!

randrange(2**30) produces a pseudo-uniformly distributed number (Mersenne Twister 219937-1) from the range [0,230). Since n is guaranteed to be below 230 this can simply be called repeatedly until it is not greater than the input. It will take a long expected time for very low values of n, but usually works within the a minute even for inputs as low as 50.

Jonathan Allan

Posted 2017-02-28T10:17:59.827

Reputation: 67 804

2You can initialize r='' as "infinity". Or, better yet, don't initialize r and instead use id everywhere for r. – xnor – 2017-02-28T17:10:14.397

3

PowerShell, 35 bytes

for(;($a=Random 1gb)-gt"$args"){}$a

Try it online!

Another rejection sampling method. This is an infinite for loop, setting the value of $a to be a Random integer between 0 and 1gb (= 1073741824 = 2^30), and keeps looping so long as that integer is -greaterthan the input $args. Once the loop is complete, we just put $a on the pipeline and output is implicit.

Note: This will take a long time if the input is a small number.

AdmBorkBork

Posted 2017-02-28T10:17:59.827

Reputation: 41 581

2

Python 2, 89 bytes

l=range(2**31)
import random
random.shuffle(l)
n=input()
print filter(lambda x:x<=n,l)[0]

Explanation

L=range(2**31)      # Create a list from 0 to 2^31 exclusive. Call it <L>.
import random       # Import the module <random>.
random.shuffle(L)   # Use 'shuffle' function from <random> module,
                    # to shuffle the list <L>.
n=input()           # Take the input -> <n>.

print
    filter(         # Create a new sequence,
    lambda x:x<=n   # where each element is less than or equal to <n>.
    ,L)             # from the list <L>.
    [0]             # Take the first element.

This is very inefficient, as it creates 2^31 integers, shuffles and filters them.

I see no point in sharing a TIO link, where it's creating such large lists, so here is a TIO link for n = 100.

Try it online!

Yytsi

Posted 2017-02-28T10:17:59.827

Reputation: 3 582

2

Java 8, 84 83 80 71 62 bytes

n->{int r;for(;(r=(int)(Math.random()*(1<<30)))>n;);return r;}

-1 byte thanks to @OliverGrégoire.
-3 bytes thanks to @Jakob.
-9 bytes converting Java 7 to Java 8.
-9 bytes by changing java.util.Random().nextInt(1<<30) to (int)(Math.random()*(1<<30)).

Explanation:

Try it here.

n->{        // Method with integer parameter and integer return-type
  int r;    //  Result-integer
  for(;(r=(int)(Math.random()*(1<<30)))>n;);
            //  Loop as long as the random integer is larger than the input
            //  (the random integer is in the range of 0 - 1,073,741,824 (2^30))
  return r; //  Return the random integer that is within specified range
}           // End method

NOTE: May obviously take very long for small inputs.

Example output:

407594936

Kevin Cruijssen

Posted 2017-02-28T10:17:59.827

Reputation: 67 575

2@Aaron I questioned this as well but see the second bullet point: "Any arguments when calling a built in or library random function must be constant. That is they must be completely independent of the input value." This is the reason max int is used. – Poke – 2017-02-28T14:11:19.307

12^30 = 1073741824. You preferred to use -1>>>1 (= 2147483647). But this exists: 1<<30 which is exactly equals to 2^30; and is 1 byte shorter. – Olivier Grégoire – 2017-03-01T16:16:14.713

1How about int c(int n){int r;for(;(r=new java.util.Random().nextInt(1<<30))>n;);return r;}? – Jakob – 2017-08-09T14:09:05.650

@Jakob Thanks. I even shortened it by 18 more bytes by using Java 8 instead of 7, and using Math.random() instead of java.util.Random().nextInt. – Kevin Cruijssen – 2017-08-09T14:54:55.357

2

Perl 6, 29 bytes

{first 0..$_,^2**30 .roll(*)}

Inspired by Martin Ender's Mathematica solution.

Generates a lazy infinite sequence of random integers between 0 and 2^30-1, and takes the first one that is between 0 and the input.

Try it online!

smls

Posted 2017-02-28T10:17:59.827

Reputation: 4 352

2

05AB1E, 11 bytes

žIÝ.rDI›_Ϥ

Try it online!

Explanation

žIÝ          # push the inclusive range [0 ... 2^31]
   .r        # get a random permutation (pythons random.shuffle)
     D       # duplicate this list
      I      # push input
       ›_Ï   # keep only elements from the list not greater than input
          ¤  # take the last one

As the list [0 ... 2147483648] is too large for TIO, the link uses 1.000.000 instead.

Alternate (on average) much faster 11 byte solution

[žIÝ.RD¹›_#

Try it online

Explanation

[             # start loop
 žIÝ          # push the inclusive range [0 ... 2^31]
    .R        # pick a random integer (pythons random.chiose)
      D       # duplicate
       ¹      # push input
        ›_#   # break if random number is not greater than input
              # implicitly output top of stack (the random number)

Emigna

Posted 2017-02-28T10:17:59.827

Reputation: 50 798

žJL.R% for 6 unless I'm missing something huge. Push 2^32, list from 0 to 2^32, random pick. Modulo input. Will absolutely screw the efficiency that you have. – Magic Octopus Urn – 2017-03-01T14:33:40.300

@carusocomputing.You'd need an I in there for 7 bytes to get the arguments for modulus in the right order (and maybe Ý instead of L), but otherwise that's certainly a shorter solution. I saw Dennis doing that in his Jelly answer, but as this was my first idea I kept this. As that approach is different from this you could post it as a separate answer. – Emigna – 2017-03-01T14:43:15.597

DI‹Ï would avoid the loop. – Magic Octopus Urn – 2017-03-01T19:35:41.647

Also, as-is, this is not guaranteed to terminate; if I'm not mistaken, an input of 0 would almost always result in a near-infinite loop, making it hard to terminate. Though the solution does allow for the possibility to terminate in all scenarios it isn't guaranteed due to randomness. – Magic Octopus Urn – 2017-03-01T19:41:40.310

@carusocomputing: For very small input the second version would on average take a very long time to finish yes, but given enough time it would. – Emigna – 2017-03-01T21:23:10.197

@carusocomputing the challenge says "Your code may terminate with probability 1 rather than being guaranteed to terminate." This submission satisfy that rule. – Martin Ender – 2017-03-01T21:59:37.547

2

Python 3, 51 bytes

Here is a python solution with an unorthodox random source.

print(list(set(map(str,range(int(input())+1))))[0])

Try it online!

So to break this down.

int(input())+1

Gets the input number, and adds 1 to it.

set(range(...))

Creates the set {0, 1, 2, 3, 4, ... n} for all possible results.

print(list(...)[0])

Takes the set, converts it to list, and grabs the first item.

This works because in Python 3, the order of set() is established by PYTHONHASHSEED (can't be obtained but is established on script execution).

Admittedly, I am guessing that this is a uniform distribution, as the hash() value is randomly assigned and I am looking at randomly picking the value with a specific hash(), rather then just returning the hash(input()) itself.

If anyone knows whether this is a uniform distribution, or how I could test that, please comment.

The Matt

Posted 2017-02-28T10:17:59.827

Reputation: 271

1

Bash + coreutils, 20 bytes

Golfed

seq 0 $1|shuf|sed 1q

shuf - generate random permutations

Shuf will use the following code: to generate permutations:

permutation = randperm_new (randint_source, head_lines, n_lines);

which ends up in randint_genmax

/* Consume random data from *S to generate a random number in the range
0 .. GENMAX.  */

randint
randint_genmax (struct randint_source *s, randint genmax) 
{
      ...

      randread (source, buf, i);

      /* Increase RANDMAX by appending random bytes to RANDNUM and
         UCHAR_MAX to RANDMAX until RANDMAX is no less than
         GENMAX.  This may lose up to CHAR_BIT bits of information
         if shift_right (RANDINT_MAX) < GENMAX, but it is not
         worth the programming hassle of saving these bits since
         GENMAX is rarely that large in practice.  */
      ...
}

which, in turn, will read a few bytes of the random data from the low-level source of randomness:

/* Consume random data from *S to generate a random buffer BUF of size
   SIZE.  */

void
randread (struct randread_source *s, void *buf, size_t size)
{
  if (s->source)
    readsource (s, buf, size);
  else
    readisaac (&s->buf.isaac, buf, size);
}

i.e. at the low-level, there is no direct dependency between the shuf input value and the data read from the source of randomness (aside from computing the required byte buffer capacity).

zeppelin

Posted 2017-02-28T10:17:59.827

Reputation: 7 884

6Isn't this giving the input as an argument to your random number generator? – Martin Ender – 2017-02-28T11:46:47.790

Even if this is not valid, please submit another bash answer! – None – 2017-02-28T11:48:09.497

@MartinEnder well, not directly, it just uses the input to define the upper limit for the generated integer range and jot will arrange for all the values in the range to appear in the output with an equal probability (that's probably borderline, but still). – zeppelin – 2017-02-28T11:52:48.650

2If I dig deep enough into any random number generator I'm sure I'll find a call into a lower-level RNG that doesn't directly use the original argument. The point of the challenge is to obtain an arbitrary-size uniform distribution from a fixed -size distribution, which you're still not doing. – Martin Ender – 2017-03-01T21:56:49.090

1

C#, 57 bytes

n=>{int x=n+1;while(x>n)x=new Random().Next();return x;};

Anonymous function which returns an integer between 0 and n inclusive.

The smaller the input number, the longer the time to return a random value.

Full program:

using System;

class RandomNumber
{
    static void Main()
    {
        Func<int, int> f =
        n=>{int x=n+1;while(x>n)x=new Random().Next();return x;};

        // example
        Console.WriteLine(f(100000));
    }
}

adrianmp

Posted 2017-02-28T10:17:59.827

Reputation: 1 592

2"Any arguments when calling a built in or library random function must be constant. That is they must be completely independent of the input value." The argument to Next is not static. – Yytsi – 2017-02-28T12:21:27.650

1

Ruby, 23 15 23 32 29 bytes

->n{1while n<q=rand(2**30);q}

How it works:

  • 1while [...]; executes the statement at least once: 1 before while acts as a nop
  • Get a random number in the range 0..2^30-1 (lower than 2^30, as specified)
  • Repeat if the number is higher than the input parameter (Could take some time when n is small)

G B

Posted 2017-02-28T10:17:59.827

Reputation: 11 099

1

SmileBASIC, 38 bytes

INPUT N@L
R=RND(1<<30)ON N<=R GOTO@L?R

Generates random numbers until it gets one that is smaller than the input.

12Me21

Posted 2017-02-28T10:17:59.827

Reputation: 6 110

1

Golang, 84 78 71 bytes

import."math/rand"
func R(n int)int{q:=n+1;for;q>=n;q=Int(){};return q}

Simple rejection sampling.

Note: since the math/rand seed is a constant 1, the caller must seed unless a constant result is desired.

Test: https://play.golang.org/p/FBB4LKXo1r No longer practically testable on a 64-bit system, since it's returning 64-bit randomness and using rejection testing.

package main

import "fmt"
import "time"

/* solution here *//* end solution */

func main() {
    Seed(time.Now().Unix())
    fmt.Println(R(1073741823))
}

Riking

Posted 2017-02-28T10:17:59.827

Reputation: 249

1if you use import."math/rand" then Int31 is available in the global namespace and you can save 4 bytes, also intis guaranteed to be at least 32 bits, saving you another 6 bytes – Kristoffer Sall-Storgaard – 2017-03-01T13:18:27.563

Use := syntax for another 3 bytes – Kristoffer Sall-Storgaard – 2017-03-01T13:30:39.307

Using int instead of int32 doesn't save any bytes since we need to cast the result of Int31() - 3int + () = 11 bytes versus 2int32 = 10 bytes. – Riking – 2017-03-01T21:53:30.203

1No need to cast, there is an Int() function in the rand package, also, you can remove the space after import – Kristoffer Sall-Storgaard – 2017-03-02T08:59:14.550

1

Ohm, 26 bytes

IΩ
D31º#╬D0[>?D-+∞;,

Explanation:

IΩ                 ■Main wire
IΩ                 ■Call wire below

D31º#╬D0[>?D-+∞;,  ■"Real main" wire
D                  ■Duplicate input
 31º#╬D            ■Push random_int in [0..2^31] twice
       0[          ■Push input again
         >?    ;   ■If(random_int > input){
           D-+     ■  remove the random_int
              ∞    ■  recursion
               ;   ■}
                ,  ■Print random_int

Roman Gräf

Posted 2017-02-28T10:17:59.827

Reputation: 2 915

Is there an interpreter for this language? And what about Code-page? – ATaco – 2017-03-01T22:18:09.150

@ATaco: Interpreter, Code-page: CP-437

– Emigna – 2017-03-02T07:08:49.647

1

Go, 63 61 bytes

import."math/rand"
var n=0;func R(){q:=n;for;q<n+1;n=Int(){}}

Use it like this:

func main() {
    n = 5000
    R()
    print(n)
}

Test it live at the go playground

Kristoffer Sall-Storgaard

Posted 2017-02-28T10:17:59.827

Reputation: 489

Per our defaults, taking input from predefined variables and writing the output to predefined variables are not allowed. You could use pointers to global variables though

– Dennis – 2017-03-31T14:39:00.753

1

R, 37 bytes

which.min(sample(2^30)[0:scan()+1])-1

Takes n from stdin. First it generates a random sample of all the integers in the range, then selects the first n+1 values, finds the index of the minimum, and then subtracts one, to generate a number between 0 and n, inclusive. It won't run on TIO because it can't allocate an array of size 2^30 to sample from.

I'm fairly confident this is uniformly random.

Try it online!

Giuseppe

Posted 2017-02-28T10:17:59.827

Reputation: 21 077

1

Braingolf, 16 bytes

Uv2.# ,-^r[R>v]R

Try it online!

Takes longer than 60 seconds on TIO, but will terminate in a finite amount of time

Explanation

Uv2.# ,-^r[R>v]R  Implicit input from commandline args
U                 Pop top of stack and push range 0...n
 v                Switch to stack 2
  2.              Push two 2s
    #<space>      Push 32 (codepoint of space)
      ,           Swap top 2 items on stack
       -          Subtract top of stack from 2nd to top
        ^         Raise 2nd to top of stack to top of stack
                  This whole bit makes 2^30 on the 2nd stack
         r        Pops top of stack and pushes a random integer <= to popped item
                  This uses Python3's randrange, between 0 and the popped item
          [...]   While loop runs X times where X is the previously generated random number
           R>     Move top of stack1 to bottom of stack1
             v    Switch back to stack2 for loop counting
               R  Switch back to stack1 for implicit output
                  Implicit output of top of stack

So in short, this generates range [0...n], then generates a random number less than or equal (<=) to 2^30, it then rotates the range that number of times, and outputs the top of the stack at the end.

Skidsdev

Posted 2017-02-28T10:17:59.827

Reputation: 9 656