Page 2 of 2

Re: How to choose source?

Posted: Sun Dec 11, 2011 3:31 pm
by vrld
Why is the first random number after randomseed() not random?

According to the lua-users wiki, a possible fix would be

Code: Select all

math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) )
It also affects only the first generated random value (and only BSD/OSX), so one additional math.random() after math.randomseed(os.time()) should be enough.

Re: How to choose source?

Posted: Sun Dec 11, 2011 3:50 pm
by Metalcookie
vrld wrote:Why is the first random number after randomseed() not random?

According to the lua-users wiki, a possible fix would be

Code: Select all

math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) )
It also affects only the first generated random value (and only BSD/OSX), so one additional math.random() after math.randomseed(os.time()) should be enough.
When I was fiddling with his code, I even tried that seed, combined with a for-loop to call math.random() 50000 times and still it would give the exact number every time on 0.8.0 but also on 0.7.2.

It's not a big deal since it somehow doesn't happen with my own projects, but it was weird nevertheless.

Re: How to choose source?

Posted: Tue Dec 13, 2011 6:32 pm
by Lafolie
I find that at least 3 randoms are needed before it starts spitting out anything different.

Re: How to choose source?

Posted: Tue Dec 13, 2011 7:41 pm
by Jasoco
Which is why I always call math.random 3 times after setting the seed for good measure.

Re: How to choose source?

Posted: Tue Dec 13, 2011 8:17 pm
by vrld
Lafolie wrote:I find that at least 3 randoms are needed before it starts spitting out anything different.
Remember that a sequence of numbers where no two neighboring numbers are the same is exactly the opposite of random. Repetitions will occur more frequently the fewer numbers you choose from. You can try it yourself by throwing a die multiple times.
For the lazy, this is such a sequence: 5, 5, 5, 3, 5, 1, 2, 4, 5, 3, 5, 4, 3, 1, 3, 1, 1, 2, 6, 4, 3, 6, 3, 1, 6, 6, 4.
I'm sure you can find some "patterns" in there. If you reduce this to three numbers by mapping 1&2 to 1, 3&4 to 2 and 5&6 to 3, you get the sequence: 3, 3, 3, 2, 3, 1, 1, 2, 3, 2, 3, 2, 2, 1, 2, 1, 1, 1, 3, 2, 2, 3, 2, 1, 3, 3, 2.

What you probably want is NOT truly random (read: statistical independent) behavior, but a "random bag", where each element is chosen randomly and then removed from the bag. Once the bag is empty, it is filled again:

Code: Select all

function random_bag(values)
    local bag = {}
    local function refill()
        for i,v in ipairs(values) do bag[i] = v end
        -- shuffle the bag
        for i=#bag,2,-1 do
            local k = math.random(1,i)
            bag[i], bag[k] = bag[k], bag[i]
        end
    end

    return function()
        if #bag == 0 then refill() end
        return table.remove(bag)
    end
end
Use it like so:

Code: Select all

bag = random_bag({"music1.mp3", "music2.mp3", "music3.mp3"})
print(bag()) --> music1.mp3
print(bag()) --> music3.mp3
print(bag()) --> music2.mp3
print(bag()) --> music1.mp3