Random with your hands tied

2

Task

Develop some code to generate a psuedo-random number between X and Y (taken as input). Explain why or how it works.

Conditions

  • Do not use any random generating seeds, pre-written randoms, or external source to generate the random number.
  • Make something as close to random as you can get. No hard coding of values.

Whoever gets the most upvotes for a new, innovative, out of the box, idea, wins.

NRGdallas

Posted 2012-07-31T19:45:13.930

Reputation: 707

Question was closed 2012-08-02T15:38:59.987

1Are we supposed to generate a seemingly random number (or sequence of numbers) that can still be the same every time run, or do we need to get different numbers for each run. For the latter we positively need some source of an external seed that differs for each time run, which might be time or a file we've written to on our last run. – shiona – 2012-07-31T20:04:04.247

2Is this a golf or a challenge ? The question says golf but the tag says challenge ? – Paul R – 2012-07-31T22:07:42.380

1what is meant by an external source? – ardnew – 2012-08-01T01:31:55.287

@ardnew: Probably means that the program should run by itself, no webpages or files are referenced. – beary605 – 2012-08-01T17:10:27.557

What exactly constitutes a "random number seed"? Any constant, noise, or any other value that is used to generate any other number can be a "seed", Can you be more precise in your definition? Also, how pseudorandom must the generator be? – Joel Cornett – 2012-08-01T17:27:59.177

its a challenge, highest upvotes win. the random should be some way of doing it unique, and should change every time. Ultimately top votes win, so just have some fun with it and think outside of the box. – NRGdallas – 2012-08-01T18:28:07.293

alot of confusion on "external source" - the intent was that you couldn't use anything that is designed for random generation. As an example, time -could- be used, BUT its not really that original...

You just can't call random.org, or use something that basically does the job for you. – NRGdallas – 2012-08-01T18:30:48.147

@NRGdallas: Thanks. That cleared it up a lot. – Joel Cornett – 2012-08-01T21:44:47.563

3"Most votes" is not an objective winning criterion in the meaning of the FAQ. The winner should be obvious to a person examining the entries. Otherwise we have a simple popularity contest. – dmckee --- ex-moderator kitten – 2012-08-02T15:40:03.137

47 answers to a question that is apparently "not a real question". This site has so many negative people on it. Why does everything have to be objective? Photography competitions are subjective; is there not some art to solving many of these problems? – Griffin – 2012-08-02T15:42:12.163

6The SO asked the readers to judge submitted routines for a pseudo random number generator, taking into account the degree to which the proposals demonstrate original, "out of the box" thinking. This is admittedly subjective, but fully reasonable as a code challenge. The question is real. It is not ambiguous, vague, incomplete or rhetorical. It can be reasonably answered, as several submissions already made clear. It should not have been closed. – DavidC – 2012-08-02T16:39:19.960

@Griffin: Photography contests that allow public voting (as opposed to being voted on by an expert panel) are just as bad, as far as being a popularity contest goes. (I come from the view that popularity contests are content-free noise, and if you've seen the popularity contests that were all the rage back in the early days of Stack Overflow, you'll know what I'm talking about.) Next thing you know, people will want to post boat-programming questions here. Just say no. – Chris Jester-Young – 2012-08-02T19:04:32.170

@DavidCarraher: If you prefer, I'll be quite happy to choose a different close reason. The one I tend to use for "subjective winning criteria" questions is "off-topic". This is a matter of site policy: if you disagree with the policy, please make a post on meta where this can be discussed (although in the specific regard of the objectivity requirement, I believe this has been discussed multiple times before...). – Chris Jester-Young – 2012-08-02T19:09:36.207

1@ChrisJester-Young: I took your reason for closing the question at face value as a sincere claim. Apparently, you do not care what reason you give once you decide to close a question. By the way, reputations on Stack Exchange are officially based on the judgment of the community about the worth of contributions, so it's not as if this criterion were foreign to the enterprise. – DavidC – 2012-08-02T19:57:27.627

1@NRGdallas: If it's a challenge then please edit the word "golf" out of the question to avoid further confusion – Paul R – 2012-08-02T21:17:58.103

@DavidCarraher: (Apologies in advance if I misread your comment.) The list of close reasons is standard across the Stack Exchange network. There isn't a special close reason called "too subjective" just for this site; instead, it straddles the line between NARQ, Not Constructive, and Off-Topic. So you have to choose one. On reflection, Not Constructive is probably a better close reason than Off-Topic. But my point remains: questions that are not even the slightest bit objective are not generally a good fit for this site. The lack of a close reason tailored for that doesn't contradict my point. – Chris Jester-Young – 2012-08-02T22:06:27.493

Answers

4

C

not sure if the volatile keyword is needed (or what other OS dependencies are assumed here)

simply takes the address of a variable, and maps it to [min, max]:

int rand(int min, int max)
{
  volatile int order = max - min + 1;
  return min + (int)&order % order;
}

ardnew

Posted 2012-07-31T19:45:13.930

Reputation: 2 177

this uses rand( generally the goal of this was to avoid using such tools – NRGdallas – 2012-08-01T18:28:37.090

9@NRGdallas uses rand? are you talking about what i named the subroutine? this solution uses no library routines. – ardnew – 2012-08-01T18:46:17.333

1This is a relatively clever way of getting one random number, so I hardly call it an rng. Due to data alignment the code (at least on my machine) will output only even numbers. I get almost only negative numbers, since the address of order is high enough to be seen as a negative in and in C(++) the %-operator takes its sign from the dividend. Still the most innovative. +1 – shiona – 2012-08-02T14:10:41.017

1

Perl

First, here is a solution that was golfed, coming in at 30 characters:

$a=<>;$b=<>;print$$%($b-$a)+$a

This solution uses the process number of the program as the random seed, similar to using the location of the variables as a seed. It works the best when the min and max are small compared to the process number.

Here is a version that uses command line arguments, with 36 chars:

 print$$%($ARGV[1]-$ARGV[0])+$ARGV[0]

And here is a version as a subroutine that returns the random value (without printing to screen), with 29 chars:

 sub a{$$%($_[1]-$_[0])+$_[0]}

Second, I am working on a solution that adheres to the strictest reading of the spec, which is that the program cannot be influenced by anything except the two arguments.

PhiNotPi

Posted 2012-07-31T19:45:13.930

Reputation: 26 739

I don't know Perl syntax very well, but couldn't you declare $ARGV as another, shorter, variable? Or just the value of $ARGV[0] to save a few characters? – MrZander – 2012-08-02T17:09:01.663

The array @ARGV is how the command line arguments are read. By removing them, I would have to take the input a different way. – PhiNotPi – 2012-08-02T18:18:53.373

1Actually, it appears that by taking input from STDIN, while causing me to add $a=<>;$b=<>;, actually saved me characters. – PhiNotPi – 2012-08-02T18:26:11.600

1

Mathematica

Rationale

Pi is an irrational number. It decimal representation does not repeat.

I strongly suspect that it does not "favor" any of the base ten digits, 0...9, nor any numbers of length when one partitions the decimal into strings of d digits. This suspicion can later be informally checked using the code below.

Code

The following will select integers between the integers x and y, where x is less than y.
y need not have the same number digits as x. The routine will begin at the cth digit of Pi. At the end of the procedure, the counter will be at c + n.

ClearAll[f]
f[x_,y_,c_,n_]:=
  Module[{diff=y-x,d},
  d=Length[IntegerDigits[diff]];
  Cases[FromDigits/@Most[IntegerDigits[Round[N[Pi,c+n+1]10^(c+n-1)]]][[c;;c+n1]]~Partition~d,
  i_/; i>x-1 && i<y+1]]

Suppose we want to generate a large (> 3000000), pseudo-random list of integers between 7 and 78. Here is how to request it. I've estimated that we'll need to use about 10^7 digits of Pi. We'll begin from position 1, that is, c=1.

(results= f[7,78,1, 10^7])//Timing

results

Note how the unsorted and untallied results maintain the order of Pi's digits: 314159... Note also that the result took just under 20 seconds. As we move further along, we'll encounter practical limits to how much we can process in a reasonable amount of time. But since this is merely an exercise in thinking out of the box, we'll ignore this limitation as we proceed.

Examining the results

When we tally and plot the results we see that Pi does not particularly favor any numbers in this range:

SortBy[Tally[results],First]

tally

Notice that the integers between 7 and 78 were chosen more or less with equanimity. Further tests would show this holds up.

ListPlot[%]

listplot

Similar checks should show whether or not Pi plays favorites with any numbers at all, regardless of how many digits it holds. [I checked for 1, 2, and 3 digit numbers over tens of millions of draws and found no bias starting from the beginning of Pi. A rigorous check would require more systematic examination or theoretical insights.]

DavidC

Posted 2012-07-31T19:45:13.930

Reputation: 24 524

0

Python

import sha
R=lambda x,y:x+int(sha.new('%d_%d'%(x,y)).hexdigest(),16)%(y-x)

Keith Randall

Posted 2012-07-31T19:45:13.930

Reputation: 19 865

Gives you the same output if you provide the same x and y. – MrZander – 2012-07-31T22:29:18.650

@MrZander: the way I interpret the spec, that is inevitable. – Keith Randall – 2012-07-31T23:38:45.283

1Hardly "innovative", why not just multiply it by the time or something like that? – MrZander – 2012-08-01T00:01:08.720

@MrZander because time is external source. If you can use time then just take microseconds since boot and map it to the given range. – shiona – 2012-08-01T09:33:30.530

Maybe I am interpreting it differently. I see "external source to generate the random" as an external source designed for random number generation. Up for interpretation, I guess. – MrZander – 2012-08-01T16:48:35.467

0

JavaScript

function getRandom(x,y) {
    s=document.createElement("SCRIPT");
    s.src="http://search.twitter.com/search.json?q=%22random%22&&callback=t"
    document.getElementsByTagName("HEAD")[0].appendChild(s);
    var c = 0;
    window.t=function (d) {
        g=d.results;
        for(z=0; z<g.length; z++) {
            c+=g[z].id/0xfff;
        }
        console.log(x+c%(y-x))
    };
}

This is pretty disgusting really. Queries Twitter, via the JASONP API, for recent tweets containing the word "random", then it uses the ID's of each of the returned tweets to calculate the "random" number.

You might want to wait a few seconds in between each call of the function, also it doesn't return a value, it just outputs one to the console. (Told you it was disgusting).

You can try it here.

Griffin

Posted 2012-07-31T19:45:13.930

Reputation: 4 349

3Nice idea, but without using ANY [...] external source. – kaoD – 2012-07-31T23:25:56.497

using twitter API, I actually think its pretty creative. Read the above comment on the post for "any external source" it has been clarified to also show this is OK :) – NRGdallas – 2012-08-01T18:31:44.450

@NRGdallas, thanks for clarifying. That's what I thought you meant by external source. – Griffin – 2012-08-01T20:43:20.013

0

Python 2.x, 454

z=lambda n,b:int("0b"+(bin(n)[2:][:-b]or'0'),2)
r=range
g=624
def m(s,t):
 a=[s]
 for i in r(1,g): a+=[1812433253*((a[i-1]^(a[i-1]>>30))+i)]
 for i in r(t):
    i%=g
    if not i:
        q=0
        for c,d in zip(a,a[1:]+[a[0]]):
            u=(z(c,1)+z(d%g,31))
            a[q]=a[(q+397)%g]^(u>>1)
            if u%2:a[q]^=2567483615
            q+=1
    y=a[i]^(a[i]>>11)
    y^=(y<<7&2636928640)
    y^=(y<<15&4022730752)
    y^=(y>>18)
    yield y

Mersenne twister algorithm. It can probably be golfed some more.

Usage:

>>> list(m(s, t))

Where s is the seed, and t is the number of numbers to generate.

Joel Cornett

Posted 2012-07-31T19:45:13.930

Reputation: 361

Unfortunately your hands are much more tied: without using ANY random generating seeds – kaoD – 2012-08-01T14:45:01.087

Do you mean "without using any external seed"? If I set seed to a constant value, for example, would that satisfy the terms of the challenge? – Joel Cornett – 2012-08-01T17:33:26.270

I guess that wouldn't be random then, but a constant. That's the challeng (though I'm not the challenge author, so feel free to ask him in comments.) – kaoD – 2012-08-01T21:35:52.517

0

Python, 32

Similar to ardnew's answer:

a,b=input()
print a+id(1)%(b-a)

Ante

Posted 2012-07-31T19:45:13.930

Reputation: 321