5

I've been asking questions on random numbers, and I decide the Fisher-Yates shuffle would be the best option. I make a table 't'

t = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

Now, how would I even shuffle these and be able to use them individually, for example generate the results in another table u

u = {}
hjpotter92
  • 78,589
  • 36
  • 144
  • 183
ZackaryCW
  • 113
  • 1
  • 7

2 Answers2

7

For those that find this answer later, this will shuffle in place without making a new table:

local function ShuffleInPlace(t)
    for i = #t, 2, -1 do
        local j = math.random(i)
        t[i], t[j] = t[j], t[i]
    end
end

And this one that returns a shuffled table without touching the original (unlike the current answer, which both shuffles in-place and returns a copy):

local function Shuffle(t)
    local s = {}
    for i = 1, #t do s[i] = t[i] end
    for i = #t, 2, -1 do
        local j = math.random(i)
        s[i], s[j] = s[j], s[i]
    end
    return s
end

Usage:

local t = {"a", "b", "c", "d", "e", "f"}

print(table.concat(t)) --> abcdef
    
local s = Shuffle(t)
    
print(table.concat(t)) --> abcdef (unchanged)
print(table.concat(s)) --> fbcade (shuffled)

ShuffleInPlace(t)
    
print(table.concat(t)) --> dcbfea (shuffled)

And a quick sanity check that they're uniform:

local t = {"a", "b", "c"}

local results = {abc = 0,acb = 0,bac = 0,bca = 0,cab = 0,cba = 0}

for i = 1, 10000000 do
    ShuffleInPlace(t)
    local r = table.concat(t)
    results[r] = results[r] + 1
end

for k, v in pairs(results) do print(k, v) end

--[[
cba 1667473
cab 1666235
bca 1665672
bac 1666782
acb 1666447
abc 1667391
--]]
MHebes
  • 2,290
  • 1
  • 16
  • 29
  • 2
    this answer is more helpful and accurate +1, the accepted one had many issues thanks for fixing them. – Phani Rithvij Nov 07 '21 at 18:22
  • I still needed `math.randomseed(os.time())` as the accepted answer has, and specifically, I needed it within the function, not outside. – shmup Aug 15 '22 at 04:49
2

NOTE: Check the other answer https://stackoverflow.com/a/68486276/1190388 which fixes an issue in the code snippet below as well as providing other alternatives

If you do not have holes in your table:

math.randomseed(os.time()) -- so that the results are always different
function FYShuffle( tInput )
    local tReturn = {}
    for i = #tInput, 1, -1 do
        local j = math.random(i)
        tInput[i], tInput[j] = tInput[j], tInput[i]
        table.insert(tReturn, tInput[i])
    end
    return tReturn
end
hjpotter92
  • 78,589
  • 36
  • 144
  • 183