Reputation: 4517
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.
Upvotes: 1
Views: 483
Reputation: 111860
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/
Upvotes: 1
Reputation: 56536
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)
Upvotes: 0
Reputation: 111259
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!
Upvotes: 5