Page 1 of 1

Shuffle Table

Posted: Mon Sep 23, 2019 11:27 am
by fingus
A Table-Function that will shuffle the Table contents by random would be helpfull.

I´m not 100% sure, maybe this can be reached by using:

Sort(array[, sortfunc])

with a randomizer sortfunc.

Re: Shuffle Table

Posted: Mon Sep 23, 2019 11:42 am
by Bugala

Code: Select all

nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Sort(nums, Function(a, b) Return(Rnd(1)) EndFunction)
For k = 0 To 9
   DebugPrint(nums[k])
Next
It is not explained very clearly in the sort documentation, but function needs to return either FALSE or TRUE (which can also be 0 or 1).

Re: Shuffle Table

Posted: Mon Sep 23, 2019 7:00 pm
by PEB
I don't really understand why, but the code Bugala suggested gives the exact same new list every time (so not really random).

This code does seem to work, though:

Code: Select all

nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
?Sort(nums, Function(a, b) Return(Rnd(2)) EndFunction)
For k = 0 To 9
	error=?DebugPrint(nums[k])
	If error<>Nil Then DebugPrint("Error")
Next

Re: Shuffle Table

Posted: Tue Sep 24, 2019 2:36 pm
by SamuraiCrow
Rnd(1) gives 1 possible integer value of 0

Rnd(2) gives 1 of 2 possible values: 0 or 1. This is due to the range select value being applied as a modulo operation.

Re: Shuffle Table

Posted: Thu Jan 16, 2020 4:17 pm
by jPV
Hmm... there seems to be something hazy here... I just stumbled upon an issue like this.

If you use this code:

Code: Select all

nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Sort(nums, Function(a, b) Return(Rnd(2)) EndFunction) 
It sometimes goes through fine, but often gives an error: "Invalid order function for sorting!"

Why it fails even though it should get valid values of 0 or 1 always?

Is this why PEB used the question mark in front of his Sort line? For a workaround for a bug?

Re: Shuffle Table

Posted: Sun Jan 19, 2020 8:11 am
by SamuraiCrow
Curiously, copying the two parameters to dummy variables alleviates the Sort check.

Code: Select all

@DISPLAY 0, {HIDDEN = True}

nums = {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"}

Function Shuffler(x, y)
	Local a=x, b=y
	Return(Rnd(2) > 0)
EndFunction

Sort(nums, Shuffler)
ListRequest("Shuffled", "Click OK to continue or Cancel to also continue", nums)

Re: Shuffle Table

Posted: Sun Jan 19, 2020 10:43 am
by jPV
@SamuraiCrow

I still get the errors with your code too...

Re: Shuffle Table

Posted: Mon Jan 20, 2020 12:11 am
by SamuraiCrow
This one won't crash and it includes another version for generic tables tested with a Unicode key value.

Code: Select all

@DISPLAY 0, {HIDDEN = True}
@VERSION 7,0

/*
 *	Table shuffler
 *
 *	Parameter:
 *	a	Table to shuffle
 *
 *	Returns:
 *		Shuffled table
 */
Function p_ShuffleTable(a)
	Local key, content, k, max, iter=Nil, Nil, {}, 0, Nil
	; create an array of the keys
	Repeat
		iter = NextItem(a, iter)
		If GetType(iter) = #NIL Then Break
		k[max] = iter
		max = max + 1
	Forever
	; Randomize table
	For key, content In Pairs(a)
		iter = k[ Rnd(max) ]
		; no point in skipping redundant keys if they are Unicode
		; the CompareStr function is probably more expensive than the swap
		a[key] = a[iter]
		a[iter] = content
	Next
	Return(a)
EndFunction

/*
 *	Array shuffler
 *
 *	Parameter:
 *	a	array to shuffle
 *
 *	Returns:
 *		Shuffled array
 */
Function p_ShuffleArray(a)
	Local key, content, iter, max=Nil, Nil, Nil, ListItems(a)
	; Randomize array
	For key, content In IPairs(a)
		iter = Rnd(max)
		If (iter <> key)
			a[key] = a[iter]
			a[iter] = content
		EndIf
	Next
	Return(a)
EndFunction


nums = {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten"}
letters = {}
strings={}
letters["a"] = "apple"
letters["b"] = "baking"
letters["c"] = "catapult"
letters["d"] = "destination"
letters["e"] = "eggplant"
letters["f"] = "farmer"
letters[0] = "what?"
letters[chr(228, #ENCODING_UTF8)] = "etc."

ListRequest("Shuffled", "Click OK or Cancel to continue", p_ShuffleArray(nums) )
letters = p_ShuffleTable(letters)
ForEach(letters, Function(k,v)
	InsertItem(strings, k.."="..v)
EndFunction)
Sort(strings, Function(a,b)
	CompareStr(a,b)
EndFunction)
ListRequest("Shuffled", "Click OK or Cancel to continue", strings)

Re: Shuffle Table

Posted: Mon Jan 20, 2020 11:20 pm
by airsoftsoftwair
jPV wrote: Thu Jan 16, 2020 4:17 pm Why it fails even though it should get valid values of 0 or 1 always?
Because it's not consistent. Using Rnd() inside the sort callback is a very bad idea because it will confuse the sort algorithm. Imagine it first compares 1<2 and the result is TRUE and the next time it does this comparison the result is FALSE. This will mess up things.