Question

I can't think of a good way to do this, and would appreciate some help, if possible!

I'm afraid I don't have any code to post yet as I haven't got that far.

I need to generate a sequence of values from 3 (or possible more) parameters in the range 0-999.

The value must always be the same for the given inputs but with a fair distribution between upper and lower boundaries so as to appear random.

For example:

function (1, 1, 1) = 423

function (1, 1, 2) = 716

function (1, 2, 1) = 112

These must be reasonably fast to produce, by which I mean I should be able to generate 100-200 during web page load with no noticeable delay.

The method must be do-able in C# but also in JavaScript, otherwise I'd probably use a CRC32 or MD5 hash algorithm.

If it helps this will be used as part of a procedural generation routine.

I had a go at asking this previously, but I think the poor quality of my explanation let me down.

I apologise if this is worded badly. Please just let me know if so and I'll try to explain further.

Thanks very much for any help.

Was it helpful?

Solution 2

Using the Marsaglia generator from the Wiki

public class SimpleMarsagliaRandom
{
    private const uint original_w = 1023;
    private uint m_w = original_w;    /* must not be zero */
    private uint m_z = 0;    /* must not be zero, initialized by the constructor */

    public SimpleMarsagliaRandom()
    {
        this.init(666);
    }

    public void init(uint z)
    {
        this.m_w = original_w;
        this.m_z = z;
    }

    public uint get_random()
    {
        this.m_z = 36969 * (this.m_z & 65535) + (this.m_z >> 16);
        this.m_w = 18000 * (this.m_w & 65535) + (this.m_w >> 16);
        return (this.m_z << 16) + this.m_w;  /* 32-bit result */
    }

    public uint get_random(uint min, uint max)
    {
        // max excluded
        uint num = max - min;
        return (this.get_random() % num) + min;
    }
}

and

simpleMarsagliaRandom = function() 
{
    var original_w = 1023 >>> 0;
    var m_w = 0, m_z = 0;

    this.init = function(z)
    {
        m_w = original_w;
        m_z = z >>> 0;
    };

    this.init(666);

    var internalRandom = function()
    {
        m_z = (36969 * (m_z & 65535) + (m_z >>> 16)) >>> 0;
        m_w = (18000 * (m_w & 65535) + (m_w >>> 16)) >>> 0;
        return (((m_z << 16) >>> 0) + m_w) >>> 0;  /* 32-bit result */
    };

    this.get_random = function(min, max)
    {
        if (arguments.length < 2)
        {
            return internalRandom();
        }

        var num = ((max >>> 0) - (min >>> 0)) >>> 0;
        return ((internalRandom() % num) + min) >>> 0;
    }    
};

In Javascript all the >>> are to coerce the number to uint

Totally untested

Be aware that what is done in get_random to make numbers from x to y is wrong. Low numbers will happen a little more times than higher numbers. To make an example: let's say you have a standard 6 faces dice. You roll it, you get 1-6. Now let's say you print on it the numbers 0-5. You roll it, you get 0-5. No problems. But you need the numbers in the range 0-3. So you do roll % 3... So we have:

rolled => rolled % 3
0 => 0, 
1 => 1, 
2 => 2, 
3 => 0, 
4 => 1, 
5 => 2, 
6 => 0. 

The 0 result is more common.

Ideone for C# version: http://ideone.com/VQudcV
JSFiddle for Javascript version: http://jsfiddle.net/dqayk/

OTHER TIPS

Here's one:

function sequence(x, y, z) {
    return Math.abs(441*x-311*y+293*z) % 1000;
}

It even produces the output from your example!

You should be able to use MD5 hashing in both C# and JS.

In C#:

int Hash(params int[] values)
{
    System.Security.Cryptography.MD5 hasher = MD5.Create();
    string valuesAsString = string.Join(",", values);
    var hash = hasher.ComputeHash(Encoding.UTF8.GetBytes(valuesAsString));
    var hashAsInt = BitConverter.ToInt32(hash, 0);
    return Math.Abs(hashAsInt % 1000);
}

In JS, implement the same method using some MD5 algorithm (e.g. jshash)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top