Im using math.random to randomly select a string from a table but it isn't always 100% random, How would i go about making it 100% random so it doesn't chose the same string two times in a row.
I'm using a setup similar to this:
[CODE]
local x = math.random( 1, 10 )
print( x )
[/CODE]
My problem is that ill get the same thing printed twice, eg. 2 and 2. I've thought about somehow storing the last number but i can't figure out how to do that.
-snip-
[QUOTE=Tupac;49962705][CODE]
local x
hook.Add( "Think", "name", function()
x = math.random( 0, 10 )
end )
[/CODE][/QUOTE]
Sorry but i don't see how that will fix my problem, maybe if you could explain. Also i only want the code to run once not evey tick.
table[math.random(0, 10)] would be the only way to get a true random every time, unless you call a function and re-define the variable each time it is called.
You can reset the seed if you want.
:snip: code wouldn't work properly
If it choses the same number twice in a row, that doesn't mean it isn't completely random. You can throw a dice twice and get the same number... But if you want to avoid this, you could try inserting your options into a table. Then generate a random number between 1 and the table size, and remove the chosen one. Just remember to reinsert it after that.
[B]Edit:[/B] Also, you could store the last chosen number into a variable, and the next time you send math.Random(), check if its the same as the last one. If that's the case, execute math.Random() again inside a while loop (LUA has while loops, right?). It should return a different number. Just make sure you don't make an endless loop.
[lua]
math.randomseed(os.time())
local x = math.random(1, 10)
print(x)
[/lua]
I think this will make it 100% random.
Here's an amazing resource over the math library in Lua:
[url]http://lua-users.org/wiki/MathLibraryTutorial[/url]
However, I agree with MaxShadow. You won't always get different numbers. Especially with only 10 numbers. Now if you had around five-thousand numbers and you had two numbers in a role be the same I'd understand. But even then, it can STILL happen.
Two numbers being the same is totally coincidental, when getting random numbers.
Technically, you can also revise your script to the following:
Having only one argument will have a random number from 1 and [i]number[/i]. So there's no point in having both of those arguments you had, really.
[lua]
math.randomseed(os.time())
local x = math.random(10)
print(x)
[/lua]
[QUOTE=Percipience;49963935][lua]
math.randomseed(os.time())[/lua]
[/QUOTE]
[URL="https://github.com/garrynewman/garrysmod/blob/c6e45c493f004d54794646cf128a26477b284b7b/garrysmod/lua/includes/util.lua#L5"]I'm pretty sure the randomseed is set as os.time() by default[/URL]- I don't think you need to set it as the same thing twice
[editline]19th March 2016[/editline]
I suppose you could try something like this if you didn't want the randomly generated number to repeat:
[CODE]
local cached -- this variable is used to cache the previously generated number
local function RandomNoRepeat( low, high )
local rand = math.random( low, high ) -- get a random number between the low and high values
if rand == cached then -- if the randomly generated number is the same as the last
if rand + 1 > high then -- check if adding 1 would make it over the limit
rand = rand - 1 -- if it would, then take away 1
else -- if it wouldn't
rand = rand + 1 -- add one instead
end
end
cached = rand -- set the cached number as the (possibly altered) random number
return rand -- return it
end
[/CODE]
(Not quite sure if this function would work properly since I haven't tested it, but as long as the high and low numbers aren't the same it should work)
Then you could just do
[CODE]
sometable[RandomNoRepeat(1,10)]
[/CODE]
To get a non-repeated random number - except this number wouldn't really be random any more since it doesn't repeat...
Also, there's always a chance of that function returning something like 1, then 2, then 1 again and so on
I decided to write a mt19937 implementation in Lua after I`ve seen this thread.
[lua]
local k_MTLength = 624
local k_BitMask32 = 0x00000000ffffffff
local k_BitPow31 = bit.lshift(1, 31)
local function printhex(d)
print(string.format("%08x", d))
end
local function mul(a, b, maxBits)
local res = 0
local negative = (a < 0 and b > 0) or (a > 0 and b < 0)
a = math.abs(a)
b = math.abs(b)
for i = 0, maxBits - 1 do
local mask = bit.lshift(1, i)
local bitV = bit.band(b, mask)
if bitV > 0 then
res = res + (bit.lshift(a, i))
end
end
if negative then
res = bit.bnot(res) + 1
end
return res
end
local function add(a, b, maxBits)
local res = 0
local c = 0
for i = 0, maxBits - 1 do
local mask = bit.lshift(1, i)
local b1 = bit.rshift(bit.band(a, mask), i)
local b2 = bit.rshift(bit.band(b, mask), i)
local v = bit.bxor(bit.bxor(b1, b2), c)
c = bit.bor(bit.bor(bit.band(b2, c), bit.band(b1, b2), bit.band(b1, c)))
res = bit.bor(res, bit.lshift(v, i))
end
return res
end
local mt19937_meta = {}
function mt19937_meta:init(seed)
self.KeyTable = {}
self.KeyTable[0] = 0
self.State = 0
self:seed(seed)
end
function mt19937_meta:seed(seed)
self.KeyTable[0] = seed
self.State = 0
for i = 1, k_MTLength - 1 do
local shift = bit.rshift(self.KeyTable[i - 1], 30)
local xored = bit.bxor(self.KeyTable[i - 1], shift)
local entry = add(mul(1812433253, xored, 32), i, 32)
self.KeyTable[i] = entry
end
end
function mt19937_meta:get(min, max)
min = min or 0
max = max or 0xFFFFFFFF
if self.State == 0 then
for i = 0, k_MTLength - 1 do
local y = add(
bit.band(self.KeyTable[i], k_BitPow31),
bit.band(self.KeyTable[(i + 1) % k_MTLength], k_BitPow31 - 1),
32)
self.KeyTable[i] = bit.bxor(self.KeyTable[(i + 397) % k_MTLength], bit.rshift(y, 1));
if y % 2 > 0 then
self.KeyTable[i] = bit.bxor(self.KeyTable[i], 2567483615)
end
end
end
local res = self.KeyTable[self.State]
res = bit.bxor(res, bit.rshift(res, 11))
res = bit.bxor(res, bit.band(bit.lshift(res, 7), 0x000000009D2C5680))
res = bit.bxor(res, bit.band(bit.lshift(res, 15), 0x00000000EFC60000))
res = bit.bxor(res, bit.rshift(res, 18))
self.State = (self.State + 1) % k_MTLength
return min + ((res % max) - min)
end
mt19937_meta.__index = mt19937_meta
function mt19937(seed)
seed = seed or 0
local new = {}
setmetatable(new, mt19937_meta)
new:init(seed)
return new
end
[/lua]
The performance isn't perfect due the manual add/mul, I had to account the overflow of uint32_t in order to have a deterministic implementation that would work along with the default implementation.
[lua]
local mt = mt19937(os.clock())
for i = 0, 10 do
print(mt:get(0, 10))
end
[/lua]
It should give some good results, see blow:
[code]
8
4
6
0
8
9
9
2
7
0
6
[/code]
[QUOTE=MPan1;49964725][URL="https://github.com/garrynewman/garrysmod/blob/c6e45c493f004d54794646cf128a26477b284b7b/garrysmod/lua/includes/util.lua#L5"]I'm pretty sure the randomseed is set as os.time() by default[/URL]- I don't think you need to set it as the same thing twice[/QUOTE]
Oh fuck, really? I didn't know that. Thanks for the info. I'll have to remember that.
what is the bloatware in this thread? I am so confused.
[lua]local old, new
function NonRepeatingRandom(min, max)
local i = 0
while (old == new) and (i < 100) do
new = math.random(min, max)
i = i + 1
end
old = new
return new
end[/lua]
This tries 100 times to give you a new random number that's different from the previous one. If it gets the same number 100 times in a row, it just gives up and returns that one, but that shouldn't happen unless you gave it min and max that are identical.
Edit: to clarify, it is plausible to get the same number 100 times in a row in a truly random environment, but pseudo-random algorithms don't tend to do that.
[QUOTE=Zeh Matt;49965619]I decided to write a mt19937 implementation in Lua after I`ve seen this thread.
[Stuff]
[/QUOTE]
Man, that's completely unnecessary... GLua already has a function to return random numbers. Also, your function returns 9 twice, so it is not solving the OP's problem.
The function MPan1 posted should work fine. It will always return the next number if its the same as the last one (unless that number is the maximum).
[QUOTE=MaxShadow;49965976]Man, that's completely unnecessary... GLua already has a function to return random numbers. Also, your function returns 9 twice, so it is not solving the OP's problem.
The function MPan1 posted should work fine. It will always return the next number if its the same as the last one (unless that number is the maximum).[/QUOTE]
I'm aware, just did it for the fun, perhaps it might gives one some insight on how those things work.
[QUOTE=Cheese_3;49962654]How would i go about making it 100% random so it doesn't chose the same string two times in a row.[/QUOTE]
by definition, the number returned is therefore not random.
[QUOTE=James xX;49967473]by definition, the number returned is therefore not random.[/QUOTE]
While we're stating random facts, I'd like to mention that your avatar always has the same rings passing the same balls - that is, each ball only ever goes through one ring. Also, each ball and ring makes exactly one rotation for every animation loop, rather than 1/5 more or 1/5 less etc. As far as gifs go, it's fairly disappointing.
As for the randomness, we surely can discuss the true definition of randomness and you are right of course in saying that a truly random system does allow for repetitions, but that doesn't do anything to help -- clearly OP needs a non-repeating RNG, regardless of whether it's "truly random" or not.
You could claim that this could educate him, and yes it could, but the way you phrased it doesn't really seem to point in that direction.
[QUOTE=Neat-Nit;49967573]While we're stating random facts, I'd like to mention that your avatar always has the same rings passing the same balls - that is, each ball only ever goes through one ring. Also, each ball and ring makes exactly one rotation for every animation loop, rather than 1/5 more or 1/5 less etc. As far as gifs go, it's fairly disappointing[/QUOTE]
Rekt by a slice of cheese drawn in MS Paint
[QUOTE=MPan1;49967594]Rekt by a slice of cheese drawn in MS Paint[/QUOTE]
Don't associate me with those sliced hooligans. I'm a full block, unsliced and ungrated. Classy.
[QUOTE=Neat-Nit;49967607]I'm a full block[/QUOTE]
You have 4 holes in you
Also you're clearly not a full block you cheap peasant
[QUOTE=MPan1;49967642]You have 4 holes in you[/QUOTE]
How dare you bring up my bullet wounds[url=https://youtu.be/dZcHy_xKAQI?t=34s]![/url]
Sorry, you need to Log In to post a reply to this thread.