Page 1 of 2

How should I scramble a table?

Posted: Wed Dec 03, 2008 11:50 pm
by Mr. Strange
I have a table of 52 elements - a deck of cards. I want to shuffle them - that is, assign each of the 52 elements to a new, unique, random location.

My first idea was to use table.sort along with some random number generator. I could assign each element a random value, and then sort by those, or maybe I could do the whole thing in one step? Someone must have figured out a slick way to do this. My potentially clumsy attempt:

(assume the random number generator has been seeded previously.)

Code: Select all

table = {}
for i=1,100 do
     table[i] = i
end

mixer = {}
for i=1, #table do
     mixer[i] = math.random()
end

... now I want to do table.sort on mixer, and apply the same transposition of elements to table. Maybe I can't do that? Could I sort table by providing a comparison function which references values in mixer?

--Mr. Strange

Re: How should I scramble a table?

Posted: Wed Dec 03, 2008 11:59 pm
by surtic
I think the "standard" way to shuffle an array is this:

Code: Select all

function shuffle(tab)
  local len = #tab
  local r, tmp
  for i = 1, len do
    r = math.random(i, len)
    tmp = tab[i]
    tab[i] = tab[r]
    tab[r] = tmp
  end
end
http://en.wikipedia.org/wiki/Fisher-Yates_shuffle

edit: you can also read a bit more at http://en.wikipedia.org/wiki/Shuffle#Sh ... algorithms which describes your method as well (which is slightly less efficient because sorting an array is slower than just traversing it).

Re: How should I scramble a table?

Posted: Thu Dec 04, 2008 12:14 am
by Kaze
surtic wrote:

Code: Select all

    tmp = tab[i]
    tab[i] = tab[r]
    tab[r] = tmp

Code: Select all

tab[i], tab[r] = tab[r], tab[i]

Re: How should I scramble a table?

Posted: Thu Dec 04, 2008 12:53 am
by Mr. Strange
surtic wrote: http://en.wikipedia.org/wiki/Fisher-Yates_shuffle

edit: you can also read a bit more at http://en.wikipedia.org/wiki/Shuffle#Sh ... algorithms which describes your method as well (which is slightly less efficient because sorting an array is slower than just traversing it).
Perfect. Thank you.

--Mr. Strange

Re: How should I scramble a table?

Posted: Thu Dec 04, 2008 9:29 pm
by surtic
Kaze, you're right... too many years of bad habits...

Sometimes I do catch myself and use the idom "a, b = b, a" but in many other cases the code just looks right to me...

Re: How should I scramble a table?

Posted: Thu Sep 13, 2012 7:58 pm
by Codex
So the earlier post was a way to shuffle a single array. (ex. a deck of cards)
Kaze wrote: -snip-
surtic wrote: -snip-

Code: Select all

function shuffle(tab)
  local len = #tab
  local r
  for i = 1, len do
    r = math.random(i, len)
    tab[i], tab[r] = tab[r], tab[i]
  end
end
For a project I'm working on, I needed to shuffle tables inside one another. (ex. table[x][y]) So after playing with the above formula a bit, I came up with this.

Code: Select all

function shuffle(tab)
  local x_len = #tab
  local r_x, r_y
  for x=1, x_len do
    local y_len = #tab[x]
      for y=1, y_len do
        r_x = math.random(x, x_len)
        r_y = math.random(y, y_len)
        tab[x][y], tab[r_x][r_y] = tab[r_x][r_y], tab[x][y]
    end
  end
end
This lets me generate an image that is stored in an [x][y] format randomly.

:ultraglee: :awesome: :ultraglee:

I'm very pleased with the result!

(edit: Also I feel this thread belongs in the support and development more than general section...?)

Re: How should I scramble a table?

Posted: Fri Sep 14, 2012 4:27 pm
by qaisjp

Code: Select all

function shuffle(tab)
  local len = #tab
  local r
  for i = 1, len do
    r = math.random(i, len)

    tab[i], tab[r] = type(tab[r])=="table" and shuffle(tab[r]) or tab[r], type(tab[i])=="table" and shuffle(tab[i]) or tab[i]
  end
end
:)

Re: How should I scramble a table?

Posted: Fri Sep 14, 2012 4:47 pm
by Roland_Yonaba
Err... Why always testing if tab[r] is a table ?

Re: How should I scramble a table?

Posted: Fri Sep 14, 2012 5:08 pm
by qaisjp
Roland_Yonaba wrote:Err... Why always testing if tab[r] is a table ?
deep scrambling - if this was the table:

Code: Select all

{
   {1, 2, 3},
   {4, {5, 6}, 7, {8, 9, {10, 11} }}
}
I'd get something like this:

Code: Select all

{
     {7, {9, {11, 10}, 8}, {6, 5}, 4},
     {2, 1, 3}
}

Re: How should I scramble a table?

Posted: Sun Sep 16, 2012 4:05 pm
by tv_user
qaisjp wrote:

Code: Select all

tab[i], tab[r] = type(tab[r])=="table" and shuffle(tab[r]) or tab[r], type(tab[i])=="table" and shuffle(tab[i]) or tab[i]
I just love these mind-twisting assignment operations! Nice and simple solution qaisjp! ^^