Re-order array

BlitzMax Forums/BlitzMax Beginners Area/Re-order array

Gavin Beard(Posted 2007) [#1]
Hi all,

just a simple one ( i think ) :-)

i have an array with 52 elements, each being of integer type and being filled with the numbers 1 to 52 respectively.

i want to reorder the elements into a random order, at the moment i use a second array and use rnd to pick numbers from 1 to 52, then use a while loop to repeat this until it has made sure that the rnd number doesnt already exist in the second array, if it doesnt the number is stored in the second array, it repeats this for all 52 elements then reorders the orig. array, only prob is with the while loop it seems very very slow, is there a better/more effecient way to do this?

many thanks


ziggy(Posted 2007) [#2]
Yes, there are faster ways.
One, wich is not the best one, but could be better is to create a TCard type with a field value.
Something like:
Type TCard
    Field Value:int
End Type

Then create the collection
Local MyCards:Tlist = New Tlist
For Local I:int = 0 to 51
    Local MyCard:TCard = New TCard
    MyCard.Value = i + 1
    MyCards.AddLast(MyCard)
Next

Then use a while to get random items and store them in an array
Local MyArray:TCard[52]
Local i:int
While i<52
    Local Index:int = rand(0,MyCards.Count()-1)
    MyArray[i] = TCards(MyCards.ValueAtIndex(index))
    MyCards.RemoveAtIndex(index)
    i:+1
wend

Haven't tested, so it may be buggy. Also, I'm not sure if there a removeatindex for liked lists, but there may be something similar. It would make a big improvement to use liks instead of values references, but anyway this should be faster than you first approach.

hope you find it usefull.


Gavin Beard(Posted 2007) [#3]
thanks, will have a try of that, it should speed it up a little bit, then i can just wrap it up in a sard shuffle method of my card deck type :-)


Floyd(Posted 2007) [#4]
The idea is to pick a random item for the first slot, then a random element from the remaining items for the second slot, etc.

In pseudocode it looks like this:

For n = 0 to 50
   k = Rand( n, 51 )
   swap kth and nth elements of array
Next



ziggy(Posted 2007) [#5]
You could also use aqrray slices, it may be even easier and faster...


Dreamora(Posted 2007) [#6]
If you want to do it fast. Use Ziggys input as beginning but don't do it the overkill approach (ValueAtIndex is a no go for heavier usage).

Store the TLink that you get on AddFirst / AddLast within your object.

Now if you want to reorder, you can use that link and the before() / after() to get the item straight in front / after in the list.
Now you can easily swap the elements by using the AddAfterLink / AddBeforeLink feature of the list. (don't forget to store the link again and to remove the previous tlink before doing so!)


Gavin Beard(Posted 2007) [#7]
wow, thanks guys, great input, didnt think there would be so many ways to shuffle a deck of cards, lol, thanks again


Perturbatio(Posted 2007) [#8]
there's a large thread on this elsewhere with many more methods :)


Gavin Beard(Posted 2007) [#9]
:-( i must be searchin for wrong things then lol


Perturbatio(Posted 2007) [#10]
http://www.blitzbasic.com/Community/posts.php?topic=54021#604696


GfK(Posted 2007) [#11]
Have an index pointer in the first array. Use a random prime number for its step size.

Increment step size (mod 52), copy to next free element in second array. Repeat until you've done it 52 times.


Gavin Beard(Posted 2007) [#12]
Ok,

What i have done is, create a method that takes the amount of 'shuffles' you want to perform, then just runs a for loop that amount of times, within that loop it picks two random numbers and swaps the elements that correspond to those two numbers. Seems to produce a good randomised stack of cards in a quick time. thanks for all your help ppl :-)