Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

non-repeating random numbers

nonnux white
NN Dez!gns
Join date: 8 Oct 2004
Posts: 90
02-22-2005 04:44
i am trying to build a list of random numbers without repeating.

i got this script working, but it takes too long to shuffle a complete 52 cards list

CODE

integer rand(float min, float max, integer total)
{
integer numero = llRound(llFrand(max - min) + min);

integer i;

integer comprimento = llGetListLength(lista); // lista is a global list that stores
// all numbers till now

for (i = 0; i < comprimento; i++)
{
if (numero == llList2Integer(lista, i))
{
numero = rand(min, max, total);
}
}
return numero;
}


later in the script i call the function in a for cycle to get all cards:
CODE

integer card = rand(1,53,53); // note that i want 52 cards...
lista = lista + card; // global list



feel free to use this script, but is too slow.
hope some1 got an improvment.


note: the script can fail if "integer total" total is too big
_____________________
Jonathan Shaftoe
... the titleless.
Join date: 11 Feb 2005
Posts: 44
02-22-2005 05:01
I'm not surprised it's slow. Consider what it's doing when you have already selected 51 of your cards and only have one left, it's generating a stream of random numbers constantly until finding the one that happens to match the card remaining.

Instead, you want to do something like:

Initialise a list 'cards' with all the possible card values.

To select a card - choose a random number between 0 and the current length of the list 'cards'. Remove the selected card from the list. Return the card.

This will be far more efficient, only requiring one random number to be generated for each card you want to select. To totally shuffle the pack, keep picking cards using this method, adding them to a new list (shuffledCards), until there are no cards left in your original cards list.

Hope that all makes sense.

Jonathan
nonnux white
NN Dez!gns
Join date: 8 Oct 2004
Posts: 90
02-22-2005 05:12
yeh u are pointing good to me

it makes sense. i know the slwoing problem was described just the way u did.

so, i will try to implement this ideia.
_____________________
Jeffrey Gomez
Cubed™
Join date: 11 Jun 2004
Posts: 3,522
02-22-2005 07:18
Just do this:

CODE
list cards = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52"];

list card_names = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52"];
// Edit the card_names list to whatever you want - "1 of Diamonds", "Queen of Spades," etc.

while(cards != [])
{
cards = llListRandomize(cards,1);
integer card = llList2Integer(cards,0);
llWhisper(0,"Your card is: " + llList2String(card_names,card - 1)");
llDeleteSubList(cards,0,0);
}


The example code will deal every card in the "deck," at a fairly rapid rate, until no cards remain. Assuming I didn't screw up, anyway. :rolleyes:
_____________________
---
nonnux white
NN Dez!gns
Join date: 8 Oct 2004
Posts: 90
02-22-2005 07:21
good. didn't tryed it yet. is perfect because the goal is return this string, like Ace of Clubs

oki donki. lets keep working! thx for help
_____________________
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
02-22-2005 08:48
Also note that your original solution was buggy: inside the loop, you might well have generated a number that you'd already passed by once. Ie, your list is [1,2,3,4], you first generate a 3, then when you get to 3 you generate a 2.. now you've got a duplicate that you didn't detect :)
nonnux white
NN Dez!gns
Join date: 8 Oct 2004
Posts: 90
final script
02-22-2005 08:50
CODE

integer cardCount;
float rows;
list lista;

Say (string msg)
{
llInstantMessage(llGetOwner(), msg);
}

shufle(float total)
{
llTriggerSound("NN rattle", 1);
list cards = [];
integer i;
for (i=0;i<total;i++)
{
cards = cards + i;
}

cardCount=0; // this damn cycle could be better! i know... :\
while(cards != [])
{
if (cardCount<13)
{
cardCount++;
}
else
{
rows = rows + .3;
cardCount = 1;
}

cards = llListRandomize(cards,1);
integer card = llList2Integer(cards,0);
string suit = getSuit(card);
integer cardN = card - (llFloor(card/13)*13)+1;
string carta = cardName(cardN) + " of " + suit;
cards = llDeleteSubList(cards,0,0);
lista = lista + carta;
// llRezObject("Back Face", llGetPos() + <-0.2*(cardCount+1)+1, .5+rows, .51>, ZERO_VECTOR, ZERO_ROTATION, 44);
// llSay(44, carta);
}

}

string getSuit(integer card)
{
integer naipN = llFloor(card/13);
string Naipe;
if (naipN == 0) Naipe = "Spades";
else if (naipN == 1) Naipe = "Hearts";
else if (naipN == 2) Naipe = "Clubs";
else if (naipN == 3) Naipe = "Diamonds";
else Naipe = "*JOKER*";
return Naipe;
}

string cardName(integer card)
{
if(card == 1) return "Ace";
if(card == 11) return "Jack";
if(card == 12) return "Queen";
if(card == 13) return "King";
return (string)card;
}

string PickACard()
{
llTriggerSound("NN pop", 1);
shufle(54);
llWhisper(0, llList2CSV(lista));
return llList2CSV(lista);
}

default
{
state_entry()
{
}

touch_start(integer total_number)
{
float startingtime = llGetTime();
llSay(44, "die"); // important for rezed objects

cardCount = 0;
rows = 0;
integer i;
string test;
lista = [];

test = PickACard();

float lifetime = llGetTime()-startingtime;
llWhisper( 0, "This script has been running for "
+ (string)lifetime
+ " seconds" );
}
}
_____________________
nonnux white
NN Dez!gns
Join date: 8 Oct 2004
Posts: 90
02-22-2005 09:15
From: Lex Neva
Also note that your original solution was buggy: inside the loop, you might well have generated a number that you'd already passed by once. Ie, your list is [1,2,3,4], you first generate a 3, then when you get to 3 you generate a 2.. now you've got a duplicate that you didn't detect :)

no, u are wrong. it was looping inside the same function till it was sure that i never duplicate a number before returning it
_____________________
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
02-22-2005 09:34
Jeffrey's solution looks fine.

But I wonder if it isn't just simpler to do this:
CODE

// original code by Jeffrey Gomez
list cards = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52"];

list card_names = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52"];
// Edit the card_names list to whatever you want - "1 of Diamonds", "Queen of Spades," etc.

cards = llListRandomize(cards,1);
integer i;
integer j = llGetListLength(cards);
for (i=0; i < j; ++i)
{
integer card = llList2Integer(cards,i);
llWhisper(0,"Your card is: " + llList2String(card_names,card - 1)");
}
If llListRandomize() is properly implemented, it shouldn't be necessary to call it inside the loop.

One curiosity: any particular reason why stringed versions of ordinals were used for cards?

Note also, if one were to start the count at 0, the "- 1" could be eliminated. ;)
Jeffrey Gomez
Cubed™
Join date: 11 Jun 2004
Posts: 3,522
02-22-2005 09:50
Yeah I know. The ordinals as cards are examples - I didn't feel like writing out the card names for him. Started with one as an example, but you're correct, gene.

Excuse me laziness. :p
_____________________
---
gene Poole
"Foolish humans!"
Join date: 16 Jun 2004
Posts: 324
02-22-2005 10:06
No worries, Jeffrey, I am the poster child for laziness. :D
Strife Onizuka
Moonchild
Join date: 3 Mar 2004
Posts: 5,887
02-22-2005 12:08
CODE

list cards = ["1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","43","44","45","46","47","48","49","50","51","52"];
// Edit the cards list to whatever you want - "1 of Diamonds", "Queen of Spades," etc.

integer i;
while (i = llGetListLength(cards))
{
i = (integer)llFrand(i - 1);
llWhisper(0,"Your card is: " + llList2String(cards,i));
cards = llDeleteSubList(cards, i, i);
}

;)
_____________________
Truth is a river that is always splitting up into arms that reunite. Islanded between the arms, the inhabitants argue for a lifetime as to which is the main river.
- Cyril Connolly

Without the political will to find common ground, the continual friction of tactic and counter tactic, only creates suspicion and hatred and vengeance, and perpetuates the cycle of violence.
- James Nachtwey
Jeffrey Gomez
Cubed™
Join date: 11 Jun 2004
Posts: 3,522
02-22-2005 12:32
I give up. That's what I get for throwing that out there at work. :rolleyes:
_____________________
---
Richard Pinkerton
Registered User
Join date: 20 Jan 2005
Posts: 125
02-22-2005 13:14
The page below has some useful information on shuffle algorithms. Take particular note of random bias.

http://www.paradisepoker.com/shuffling.html
Lex Neva
wears dorky glasses
Join date: 27 Nov 2004
Posts: 1,361
02-23-2005 09:00
From: nonnux white
no, u are wrong. it was looping inside the same function till it was sure that i never duplicate a number before returning it


Right... I missed the recursion... but I still think your original algorithm didn't exactly do what you wanted it to do...
nonnux white
NN Dez!gns
Join date: 8 Oct 2004
Posts: 90
02-23-2005 10:58
From: Lex Neva
Right... I missed the recursion... but I still think your original algorithm didn't exactly do what you wanted it to do...


i tested it many times, never got any repeated card. also never crashed, but i beleive it could crash, since it produces so many iterations

anyway, the solution was using a list, and remove each crad after shufle, and it is done.


i am not a expert on scripting, that's why so many things can be done in another way in my solution.
_____________________