9
\$\begingroup\$

Computers do not out-of-nowhere create random numbers without basis, as most likely, time is the universal basis of randomness.

I want you to create a code that creates random numbers with these rules:

  • Time is not allowed to be the basis, at any point of the program.
  • Predefined random/pseudo-random functions are not allowed.
  • Numbers generated can be within any range. Well at least two different integers :D
  • Numbers are echoed.
\$\endgroup\$
8
  • 2
    \$\begingroup\$ It is unclear what you mean by "Numbers generated can be within any range". Do you mean the coder is free to choose a range? Or that they must support any range the user requests? Both of these are problematic. If the user requests a range, what if they request numbers outside the bounds of the built in data types? And if the coder is free to choose, I choose integers between 1 and 1. :D \$\endgroup\$ Mar 2, 2014 at 14:25
  • 2
    \$\begingroup\$ Should have been a code-golf... \$\endgroup\$ Mar 2, 2014 at 15:30
  • \$\begingroup\$ I started this question as popularity-question, would code-golf a better fit for this? \$\endgroup\$
    – Aesthetic
    Mar 3, 2014 at 1:19
  • \$\begingroup\$ @Daniel Yeah but let this question be popularity-question and post a new question with code golf with new rules(on random generation) that'll be fun \$\endgroup\$ Mar 3, 2014 at 2:37
  • 1
    \$\begingroup\$ using the internet as a seed seems like cheating doesn't it? \$\endgroup\$ Mar 6, 2014 at 2:22

15 Answers 15

6
\$\begingroup\$

JavaScript

That was fun!

arr = []
index = 0

function init(seed) {
    index = 0
    arr[0] = seed
    for (var i = 1; i < 624; i ++) {
        arr[i] = (1812433253 * (arr[i-1] ^ (arr[i-1] >>> 30)) + i) | 0
    }
 }

function getNumber() {
    if (index == 0) generateNumbers()

    var y = arr[index]
    y ^= (y >>> 11)
    y ^= ((y << 7) & 2636928640)
    y ^= ((y << 15) & 4022730752)
    y ^= (y >>> 18)

    index = (index + 1) % 624
    return y
}

function generateNumbers() {
    for (var i = 0; i < 624; i ++) {
        var y = (arr[i] & 0x80000000) + (arr[(i+1) % 624] & 0x7fffffff)
        arr[i] = arr[(i + 397) % 624] ^ (y >>> 1)
        if (y % 2 != 0) arr[i] ^= 2567483615
    }
}

// let's get our seed now from the SE API
var x = new XMLHttpRequest()
x.open('GET', 'http://api.stackexchange.com/2.2/answers?pagesize=10&order=desc&sort=activity&site=stackoverflow&filter=!Sri2UzKb5mTfr.XgjE', false)
x.send(null)
// we've got the answer data, now just add up all the numbers.
// only 4 digits at a time to prevent too big of a number.
var seed = 0
var numbers = x.responseText.match(/\d{0,4}/g)
for (var i = 0; i < numbers.length; i++) seed += +numbers[i]

init(seed)
for (var i = 0; i < 10; i++) console.log(getNumber())

I wrote up the Mersenne Twister in JS. Then, I realized I had to get a seed from somewhere.

So, I decided I would get it from the Stack Exchange API! (I could use localStorage and increment a counter, but that's no fun.) So, I grabbed the 10 most recently active answers, and then I just took every 4 or less consecutive digits in the response and added them up.

These seeds are always different, since Stack Overflow is constantly updating (and my quota keeps going down!) The numbers include answer IDs, question IDs, scores, up/downvote counts, owner rep/IDs, and the wrapper data (quota and such). On one run I got 256845, then 270495, and then 256048, etc....

This logs 10 random 32-bit two's-complement numbers to the console. Sample output:

247701962
-601555287
1363363842
-1184801866
1761791937
-163544156
2021774189
2140443959
1764173996
-1176627822
\$\endgroup\$
5
\$\begingroup\$

Java

import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

/**
 *
 * @author Quincunx
 */
public class NoTimeRandom extends Random {

    private AtomicLong seed;

    public NoTimeRandom() {
        byte[] ba = (new String[0].toString() + new String[0].toString()
                + new String[0].toString() + new String[0].toString()
                + new String[0].toString() + new String[0].toString()).getBytes();
        int seed1 = 1;
        for (byte b : ba) {
            seed1 += b;
        }

        ba = (new String[0].toString() + new String[0].toString()
                + new String[0].toString() + new String[0].toString()
                + new String[0].toString() + new String[0].toString()).getBytes();
        long seed2 = 1;
        for (byte b : ba) {
            seed2 += b;
        }

        seed = new AtomicLong(seed1 ^ seed2);
    }

    @Override
    protected int next(int bits) {
        long oldseed, newseed;
        AtomicLong seed = this.seed;
        do {
            oldseed = seed.get();
            newseed = (oldseed * 25214903917L + 11) & 281474976710655L;
        } while (!seed.compareAndSet(oldseed, newseed));

        return (int) (newseed >>> (48 - bits));
    }

    public static void main(String[] args) {
        Random r = new NoTimeRandom();

        for (int i = 0; i < 5; i++) {
            System.out.println(r.nextInt());
        }
    }

}

The magic is in the public NoTimeRandom(). Arrays cast to strings can confuse new programmers, as the numbers are random. Sample (for char[]: [C@4a8e91eb). The next method is copied from java.util.Random.

Sample output:

134277366
467041052
-555611140
-1741034686
1420784423

Let's test the effectiveness of this rng:

In my answer to Approximate a Bell Curve, the data generation I used depends on a good rng. Let's run it with this as the rng. Output:

enter image description here

Just as I thought. This is a pretty lousy rng.

\$\endgroup\$
0
5
\$\begingroup\$

C

Compile with the -pthread flag (or whatever your compiler uses).

#include <stdio.h>
#include <pthread.h>

#define m (unsigned long)2147483647
#define q (unsigned long)127773
#define a (unsigned int)16807
#define r (unsigned int)2836 

static unsigned long seed;
pthread_t t[20];
int lo, hi, done;

void *pseudorandom(void *id)
{
    while(done)
    {
        int test;
        hi = seed/q;
        lo = seed%q;
        test = a * lo - r * hi;
        if (test > 0) seed = test;
        else seed = test + m;
    }
}

main()
{
     int i;
     seed = 54321;
     done = 1;

     for(i = 0; i < 20; i++) 
     {
          pthread_create(&(t[i]), NULL, &pseudorandom, NULL);
     }

     for (i = 0; i < 10; i++) 
     {
          printf("%lu\n", seed);
     }

     done = 0;
}

I'm not sure if this qualifies or not based on the "time is not allowed" standard, because it is basically using the scheduler as the source of entropy by intentionally ignoring thread safety. It works by using a fairly basic psuedo-random function (Lehmer random number generator) with a hard coded initial seed. It then starts 20 threads that all run the Lehmer calculation with a shared set of variables.

Seems to work fairly well, here are a couple of consecutive runs:

comintern ~ $ ./a.out
821551271
198866223
670412515
4292256
561301260
1256197345
959764614
874838892
1375885882
1788849800
comintern ~ $ ./a.out
2067099631
953349057
1736873858
267798474
941322622
564797842
157852857
1263164394
399068484
2077423336

EDIT: Gave this a little more thought and realized that this isn't time based at all. Even with a completely deterministic scheduler, the entropy isn't coming from the time slices - it is coming from the loading of all the running processes on the system.

EDIT 2 After taking some inspiration from @Quincunx posting a bell curve, I dumped 12MB of randomness into a file and uploaded it to CAcert. It failed all of the diehard tests, but clocked a respectable 7.999573 out of 8 on the ENT test (only Potentially deterministic). Curiously, doubling the thread count made it worse.

\$\endgroup\$
4
\$\begingroup\$

C

It generates a random number in the 0-255 range by taking the seed from https://stackoverflow.com/questions using wget.

#include <stdio.h>
main()
{
    FILE *file;
    unsigned char c,x;
    system("wget -O - https://stackoverflow.com/questions > quest.html");
    file = fopen ("quest.html", "r");
    while(c=fgetc(file) != EOF) x+=c;
    fclose(file);
    printf("%d",x);
}

Sample run:

C:\Users\izabera>random
--2014-03-02 16:15:28--  https://stackoverflow.com/questions
Resolving stackoverflow.com... 198.252.206.140
Connecting to stackoverflow.com|198.252.206.140|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 85775 (84K) [text/html]
Saving to: `STDOUT'

100%[======================================>] 85,775      40.3K/s   in 2.1s

2014-03-02 16:15:31 (40.3 KB/s) - `-' saved [85775/85775]

15 /* <=================== THIS IS THE RANDOM NUMBER */
C:\Users\izabera>random
--2014-03-02 16:15:36--  https://stackoverflow.com/questions
Resolving stackoverflow.com... 198.252.206.140
Connecting to stackoverflow.com|198.252.206.140|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 85836 (84K) [text/html]
Saving to: `STDOUT'

100%[======================================>] 85,836      50.0K/s   in 1.7s

2014-03-02 16:15:38 (50.0 KB/s) - `-' saved [85836/85836]

76
C:\Users\izabera>random
--2014-03-02 16:15:56--  https://stackoverflow.com/questions
Resolving stackoverflow.com... 198.252.206.140
Connecting to stackoverflow.com|198.252.206.140|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 85244 (83K) [text/html]
Saving to: `STDOUT'

100%[======================================>] 85,244      36.0K/s   in 2.3s

2014-03-02 16:15:59 (36.0 KB/s) - `-' saved [85244/85244]

144
\$\endgroup\$
2
\$\begingroup\$

C++

#include<iostream>
int main()
{
    int *ptr=new int,i=0;
    for(;i<5;i++)
    {
        std::cout<<*(ptr+i)<<'\n';
    }
    return 0;
}  

output

any 5 random numbers

three samples
enter image description here

enter image description here

enter image description here

\$\endgroup\$
5
  • 1
    \$\begingroup\$ 1st, 2nd and 5th are pretty close, same pattern repeated in all 3 examples. not exactly the expected output from a random number generator. \$\endgroup\$
    – izabera
    Mar 3, 2014 at 2:41
  • \$\begingroup\$ @izabera When it comes to pointers in generating random numbers...everything depends on your computer(the RAM and processor) maybe the address fed by 'new int' into 'ptr' is being currently used! You tried to running this code ? \$\endgroup\$ Mar 3, 2014 at 2:49
  • \$\begingroup\$ Let me add a little change \$\endgroup\$ Mar 3, 2014 at 2:53
  • \$\begingroup\$ i tried it now, on my machine it seems like i always get things like 11230576, 0, 11206992, 0, 2053725299, which still doesn't seem random to me. \$\endgroup\$
    – izabera
    Mar 3, 2014 at 3:00
  • \$\begingroup\$ check it out at ideone \$\endgroup\$
    – izabera
    Mar 3, 2014 at 3:04
2
\$\begingroup\$

perl

What's all this rubbish with getting seeds over the internet? Sounds like cheating to me ;-) I prefer to give my seed to a cryptographic hash function instead, and give output in the range 0 to 2^160-1 like so:

use Digest::SHA1 qw(sha1);
use bigint;
sub r {
  $_ = \3;
  /^.*x([0-9a-f]+).$/;
  hex((unpack "H*", sha1 "some_salt".$1.$$)[0])
}
print join " ", r'

Anytime you have entropy of uncertain quality, a way to distribute it more regularly (but not increase its quality!) is to pipe it into the likes of SHA1 or MD5 or so, as I've done here. For pre-hash seeds, I've used pid and the address of a random reference. You could of course add other inputs for more entropy, eg on x86 you can use TSC - (but inlining assembly code in perl is a bit of a bear, so I skipped it).

If you want to have different output than the guy on the next computer over, simply adjust "some_salt" to be a string of your liking. Or leave it out altogether if you are a minimalist =)

\$\endgroup\$
3
  • \$\begingroup\$ I'd guess that any cryptographic function worth its name in a standard library uses a cryptographically secure RNG internally. \$\endgroup\$
    – duci9y
    Mar 8, 2014 at 14:22
  • \$\begingroup\$ I'm not sure about that. Digest::MD5 / Digest::SHA1 produce completely deterministic, repeatable output, so what does it need a random number for? \$\endgroup\$ Mar 8, 2014 at 14:25
  • \$\begingroup\$ Sorry! I just flew over your answer and thought that you were generating a key instead of a digest. \$\endgroup\$
    – duci9y
    Mar 8, 2014 at 14:40
2
\$\begingroup\$

Java

My solution abuses hashCode() method of Object class.

class G22640 {
    static class Rand {
        public int nextInt() {
            return new Object().hashCode();
        }
    }

    public static void main(String args[]) {
        Rand r = new Rand();
        for (int i = 0; i < 10; i++) {
            System.out.println(r.nextInt());
        }
    }
}

Sample output:

31859448
22101035
11593610
4580332
25736626
32157998
3804398
32440180
19905449
2772678

Motivated by other answer's demonstrating the randomness of the solution, I changed my solution to return the middle 16 bits of the int returned by Object.hashCode().

import java.io.*;

class G22640 {
    static class Rand {
        public short nextShort() {
            return (short) ((new Object().hashCode() >> 8) & 0xFFFF);
        }
    }

    public static void main(String args[]) throws IOException {
        Rand r = new Rand();

        for (int i = 0; i < 10; i++) {
            System.out.println(r.nextShort());
        }

        // generateToFile("random_22640.txt");
    }

    private static void generateToFile(String fileName) throws IOException {
        Rand r = new Rand();
        BufferedOutputStream o = new BufferedOutputStream(new FileOutputStream(fileName));

        for (int i = 0; i < 10000000; i++) {
            int a = r.nextShort();
            for (int j = 0; j < 2; j++) {
                o.write(a & 0xFF);
                a >>= 8;
            }
        }

        o.flush();
        o.close();
    }
}

I generated a 19 MB file (consisting of 107 short) and submit it to CACert. Here is the screenshot of the result (it has been edited to look nice, but the numbers are left as it is):

Result

I was surprised at the result, since it clocks 7.999991 at Entropy test and passes (?) all 7 Diehard tests.

\$\endgroup\$
2
\$\begingroup\$

Javascript
Generating random with user mouse move

var ranArr=[];
var random=0;
var first=second=0;
function generateR(event) {
ranArr.push(parseFloat(event.clientX+document.body.scrollLeft))
ranArr.push(parseFloat(event.clientY+document.body.scrollTop));
var len=ranArr.length;

for(var i=0;i<len;i++) {
    if(i<len/2) {

    first+=ranArr[i];
    } else {
    second += ranArr[i];
    }
}
third = second/first;
third = third+"";
console.log(third.substr(5));
}
document.onmousemove=function(event){generateR(event)};

Last five copied data:
9637090187003
7828470680762
6045869361238
4220720695015
2422653391073

\$\endgroup\$
1
\$\begingroup\$

Bash, range: ints between 0 and 1

echo -n & echo "$! % 2" | bc
\$\endgroup\$
5
  • \$\begingroup\$ So you mean it picks 0 or 1 only? \$\endgroup\$
    – user10766
    Mar 4, 2014 at 0:38
  • \$\begingroup\$ Yep. Should fulfill "Numbers generated can be within any range. Well at least two different integers :D", shouldn‘t it? \$\endgroup\$
    – Keba
    Mar 4, 2014 at 0:40
  • \$\begingroup\$ I guess so. Do you think you could expand it to a bigger range? \$\endgroup\$
    – user10766
    Mar 4, 2014 at 0:44
  • \$\begingroup\$ Just echo -n & echo $! will do, but be a very bad RNG. You can also change 2 with any other number, but the bigger the number, the worse gets the "randomness". \$\endgroup\$
    – Keba
    Mar 4, 2014 at 7:52
  • \$\begingroup\$ I see. Thanks for the explanation. \$\endgroup\$
    – user10766
    Mar 4, 2014 at 16:17
1
\$\begingroup\$

Ruby

Unfortunately Mac only. We use sox to pull bytes from the microphone (as a string, ahem...), reverse it to get the status header on the end (*cough*), chop it up, chop off the header, take the MD5 of the chunks, ditch the non-numeric chars from the hash, add the remaining largish integers together, stick a 0. on the front, convert to a float, done.

Generates floats of varying length on the interval 0..1.

require 'open3'
require 'digest'

class InsecureRandom
  def self.random_number
    n = self.get_bytes
    .map! { |r| Digest::MD5.hexdigest(r) }
    .map! { |r| r.gsub(/[a-z]/, '') }
    .map!(&:to_i)
    .reduce(0,:+)

    "0.#{n}".to_f
  end

  private
  def self.get_bytes
    Open3.popen3('sox -d -q -e unsigned-integer -p') do |_, stdout, _|
      stdout.read(20000).reverse.split('\\').to_a.take(20)
    end
  end
end

randomish = Array.new(20) { InsecureRandom.random_number }
puts randomish
# >> 0.2333530765409607
# >> 0.17754047429753905
# >> 0.936039801228352
# >> 0.2781141892158962
# >> 0.6243140263525706
# >> 0.1583419168189452
# >> 0.2173713056635174
# >> 0.930577106355
# >> 0.11215268787922089
# >> 0.13292311877287152
# >> 0.14791818448435443
# >> 0.4864648362730452
# >> 0.5133193113765809
# >> 0.3076637743531015
# >> 0.16060112015793476
# >> 0.7294970251624926
# >> 0.18945368886946876
# >> 0.9970215825154781
# >> 0.13775531752383308
# >> 0.5794383903900283
\$\endgroup\$
1
\$\begingroup\$

C

Generating random using process ID.

#include <unistd.h>
#include <stdio.h>

int     main(void)
{
    int out;
    out *= out *= out = getpid();
    printf("%d\n", out % 1024);
    return (0);
}

Sample output :

-767
0
769
-1008
337
-768
369
-752
-415
0
-863
784
-463
256
657
\$\endgroup\$
1
\$\begingroup\$

SPIN

If this was , i would win!

byte a
?a@
\$\endgroup\$
0
\$\begingroup\$

python

Python's conciseness never ceases to amaze. Since using imgur's random image is not valid apparently, I've used a great source of randomness: stackoverflow's chat!

   import urllib.request

def getrand():
    req = urllib.request.Request("http://chat.stackoverflow.com/")
    response = urllib.request.urlopen(req)
    the_page = str(response.read())
    
    x = 1
    for char in the_page:
        x = (3*x + ord(char) + 1)%2**32
        
    print(x)

5 trials:

3258789746
1899058937
3811869909
274739242
1292809118

Not truly random but then again none of these are.

\$\endgroup\$
5
  • \$\begingroup\$ i think rule 2 doesn't allow urls like whatever.com/random \$\endgroup\$
    – izabera
    Mar 3, 2014 at 3:09
  • \$\begingroup\$ @izabera 2 of the other answers used it? \$\endgroup\$
    – qwr
    Mar 3, 2014 at 3:11
  • \$\begingroup\$ nope, you're explicitly using randomly generated content. the other answers just access to some non-random webpage to get a seed and then print a random number. \$\endgroup\$
    – izabera
    Mar 3, 2014 at 3:30
  • \$\begingroup\$ @izabera I've changed my random source. What do you think of it now? \$\endgroup\$
    – qwr
    Mar 3, 2014 at 6:28
  • \$\begingroup\$ now it's fine :D \$\endgroup\$
    – izabera
    Mar 3, 2014 at 6:33
0
\$\begingroup\$

perl

I saw a lot of answers which made HTTP requests, which seems wasteful to me because under the covers there are random numbers being passed about on the wire. So I decided to write some code to swipe one at a lower level:

use IO::Socket::INET;
print ((sockaddr_in(getsockname(IO::Socket::INET->new(
    PeerAddr => "google.com", PeerPort => 80, Proto => "tcp"
))))[0]);

Gives random ports in the range 0..65535, theoretically. In practice, there are a number of ports you will never see, so the distribution is far from perfect. But it is, AFAICT the minimal amount of work you can do to get some entropy from a remote host that has a port open.

PS - Error handling is left as an exercise to the reader ;-)

\$\endgroup\$
0
\$\begingroup\$

C

// alternating two pure-RNG inspired by http://xkcd.com/221/
int getRandomNumber()
{
   static int dice_roll = 0;
   dice_roll++;
   if ((dice_roll % 2) == 1)
   {
      return 4;
   } 
   else
   {
      return 5;
   } 
}

int main(int argc, char **argv)
{
    printf("%d\n%d\n", getRandomNumber(), getRandomNumber())
    return 0;
}
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.