What happened to the Messenger Plus! forums on msghelp.net?
Shoutbox » MsgHelp Archive » Messenger Plus! for Live Messenger » Scripting » Random numbers, prevent from being used more than once

Pages: (4): « First « 1 [ 2 ] 3 4 » Last »
Random numbers, prevent from being used more than once
Author: Message:
roflmao456
Skinning Contest Winner
****

Avatar

Posts: 955
Reputation: 24
29 / Male / Flag
Joined: Nov 2006
Status: Away
RE: Random numbers, prevent from being used more than once
another suggestion:

instead of putting the lyrics on the script (big filesize)
you can put it on a webserver then call a 'httpwebrequest' object?
[quote]
Ultimatess6
: What a noob mod
07-04-2007 05:22 PM
Profile PM Web Find Quote Report
Volv
Skinning Contest Winner
*****

Avatar

Posts: 1233
Reputation: 31
34 / Male / Flag
Joined: Oct 2004
RE: Random numbers, prevent from being used more than once
quote:
Originally posted by stu
foaly, in your code, what does "count=count%9;" that line mean? Never seen that before..
The % operator is the modulo, it gives you the remainder when dividing by the number ie. the remainder when dividing count by 9. Because of the way that the function is coded, you should replace 9 with the number of lyrics you want to be displayed before you want repetition minus one (so if you want 20 lyrics you would do count%19).

This post was edited on 07-04-2007 at 05:48 PM by Volv.
07-04-2007 05:47 PM
Profile PM Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: Random numbers, prevent from being used more than once
What is being requested can be done in essentially just 3 steps/lines of code!!

(if you don't count in 1 line for generating the initial random number and 1 line to return the new lyric, which each method would have...)

And if it wasn't for the 'undefined' problem, it would be just 2 steps/lines of code!!!!



----------------------------------------------------------------------



quote:
Originally posted by Volv
I think foaly's is the simplest working code.
Actualy foaly's method is not going to work, it is fatfreechicken's method which would be working.

The method used by fatfreechicken (although a bit overcomplicated than it needs to be) is actually a very widely used method to generate a random set of numbers in such a way that no number will be drawn twice (or trice, quar...blah, whatever. :D)...

foaly's method doesn't return anything if the randomly generated lyric already exists in the past 10 lines! His function would simply stop. And even if it was fixed to regenerate a new random number when the current one already exists instead of simply quiting (which I assume is what he wanted to do ;)), his method will be dead slow because in the worst case scenario his routine would take a very long time because it constantly draws a number/lyric which was already used before and thus it needs to regenerate a new one again. The bigger the ratio of uniqueness vs the number of lyrics is, the slower such a routine will become (eg: use his routine to generate lyrics out of 100 possible lyric lines where 99 continues lines can't have the same lyric... it would take a very long time).

roflmao456's method simply fills some random items of an array (not even all items for that matter).

markee's method is a variation on what I had done (though I didn't posted this yet because I was at work all day). But it is again overcomplicated and containes the big and slow 'regenerate until you have a valid number' kind of infinite loop like foaly....



----------------------------------------------------------------------



quote:
Originally posted by Volv
Although I think instead of:
count=count%9
You should replace it with:
count= (count==9 ? 0:count);

Because you don't want to have unnecessarily large integers being stored in memory.
it wouldn't make a difference.




----------------------------------------------------------------------



Here is my method:

(it might be possible that this is what fatfreechicken wanted to do in the first place though):

You have an array full of all the possible lyric lines (to choose from).
You have (currently an empty) array of used lyrics.

STEP 1:

Each time you draw a new random lyric line you remove that lyric line from your original array and add it to the array of used lyrics.

Now your original array wont contain that lyric line anymore.  And thus there is no need to check anything at all, you wont be able to choose it again anyways (= no unneeded and long loops like with foaly's method).

STEP 2:

Move the 10th element of the used lyrics array back to the original big array of lyrics (because you must be able to choose it again).

DONE!

Do this for as long as you want... The function would be instant, no loops at all! And it always makes sure you would have 10 different lines... thus no infinite loops, not even a slow 'check against all array elements' check...

useable directly out of the box:
code:
var arrLyrics = new Array();
var arrPrevious = new Array();
var nUniqueness = 10; // positive number, should always be lower than the total number of possible lyric lines!

function GetAllLyrics() {
        // normally you read in all the possible lyrics from a file here
        return Array("A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z")
}

function GetRandomLyric() {
        // get a random lyric line from the 'possible lyrics' array
        var rndLyric = Math.floor(Math.random() * arrLyrics.length);
        // step 1: add new line to 'used lyrics' array and remove it from the 'possible lyrics' array
        arrPrevious[nUniqueness-1] = arrLyrics.splice(rndLyric, 1);
        // step 2: add last lyric line from the 'used lyrics' array back to the 'possible lyrics' array
        if (arrPrevious[0] !== undefined) arrLyrics.push(arrPrevious[0]);
        // step 3: remove last lyric line from the 'used lyrics' array
        arrPrevious.shift();
        // you're done: return the new lyric line
        return arrPrevious[nUniqueness-2]
}

// EXAMPLE START (get 20 lyrics)
        arrLyrics = GetAllLyrics();
        for (var i=0; i<20; i++) {
                Debug.Trace('New lyric: ' + GetRandomLyric());
        }
// EXAMPLE END


;)


EDIT: PS: stu, don't forget to use the var statement if you use/initialize a new variable inside a function. Not doing so will make that variable a global variable instead of a local variable.

This post was edited on 07-05-2007 at 12:53 AM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
07-05-2007 12:34 AM
Profile PM Find Quote Report
stu
Junior Member
**

Avatar
Stu

Posts: 82
Reputation: 1
38 / Male / Flag
Joined: Sep 2004
O.P. RE: Random numbers, prevent from being used more than once
Ok, so like CookieRevised said, the suggestions made did not work.. so I guess its not just me not being able to get them to work, lol. Cookie, I will give yours a try now, it looks like I will need to make a few adjustments to it to make it work with my script though, so I'll let you know how that turns out, thanks :)
07-05-2007 12:51 AM
Profile E-Mail PM Web Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: Random numbers, prevent from being used more than once
quote:
Originally posted by stu
Cookie, I will give yours a try now, it looks like I will need to make a few adjustments to it to make it work with my script though
I don't see what you need to adjust...

The function GetRandomLyric() can be used without any modification, as long as your lyrics array is named 'arrLyrics'.

The build-in lyrics array you have in your script (named Text[]) can simply be overwritten with the array read from the file (named Lines[]). You don't need two different arrays for that. Name them both arrLyrics[], stick in the routine I showed and you're done...

PS: and make your 'FileToArray' code as a seperate function and let it simply return an array so you can do:
if (which === 0) arrLyrics  = FileToArray('C:\\quotes.txt'));
or, to preserve the contents of the existing array also:
if (which === 0) arrLyrics.concat(FileToArray('C:\\quotes.txt'))

;)



code:
function FileToArray(sFileName) {
        var arrTemp = new Array();
        var oFSO = new ActiveXObject("Scripting.FileSystemObject")
        if (oFSO.FileExists(sFileName)) {
                var oFile = oFSO.OpenTextFile(sFileName, 1);       
                while(!oFile.AtEndOfStream) {
                        var sLine = oFile.ReadLine().replace(/^\s+|\s+$/g,'');
                        if (sLine !== '') arrTemp.push(sLine);
                }
                oFile.Close();
        }
        return arrTemp;
}


quote:
Originally posted by stu
Ok, so like CookieRevised said, the suggestions made did not work..
they work, but it can be done in a much shorter and faster way.

This post was edited on 07-05-2007 at 03:59 AM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
07-05-2007 12:55 AM
Profile PM Find Quote Report
stu
Junior Member
**

Avatar
Stu

Posts: 82
Reputation: 1
38 / Male / Flag
Joined: Sep 2004
O.P. RE: Random numbers, prevent from being used more than once
my array is called Text, so i renamed your code appropriately, as well as your random number variable, to Number, as it is in my code (I attached my code in one of my previous posts, if you havent seen it).  So right now other then that, its just copied straight in, and it doesnt seem to be working, or returning any lyric for that matter, just undefined. Going to further look into it now..
07-05-2007 01:03 AM
Profile E-Mail PM Web Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: Random numbers, prevent from being used more than once
Seeing your code you need to do more than that...

What you've been requesting in this thread is for an array which doesn't change.

Your code shows that you also change the array completely (the which variable and use).

But in doing so, you actually make it yourself very hard...

The use of the random variable which is wrong. You check upon it inside the personalMessage() function each time you want to change the PSM. Way easier and way more efficient is that you check on it outside of the personalMessage().

And according to what which is, you create your arrLyrics[] array.

So, instead, just make an array of only the lyrics (the old case where which is 1) or make an array of only all the external files (the old case where which is 0), or make an array of everything (not currently implemented in your existing script, but extremely easy to do if you follow my advise ;)).... You don't need to have different arrays for everything, it is all the same array which you simply (re)create according to what you want... This is done in the GetAllLyrics() function in my example code.

That is why it is there; it initializes the array you're going to use. And you call that function (GetAllLyrics()) each time the user changes the script preferences (which I assume is what which eventually will reflect).

So, since the array is created outside the personalMessage() function, you don't need to bother to see from which array you draw a random line from. AND(!) the stuff you want (don't draw the same line for x times) will work.

Hence why I suggested to just rename your stuff instead. Because if you're going to change your code over time and make your code more efficient as you go, you would end up renaming your arrays and variables the same anyways...


This post was edited on 07-05-2007 at 02:00 AM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
07-05-2007 01:32 AM
Profile PM Find Quote Report
stu
Junior Member
**

Avatar
Stu

Posts: 82
Reputation: 1
38 / Male / Flag
Joined: Sep 2004
O.P. RE: Random numbers, prevent from being used more than once
Ok, so if I was to do it as you suggest, outside my personalMessage function I would check to see what which is.. But thats not how I want the script to work though. The reason the which statement is there, is for when the script calls the personalMessage function to get a new personal message, the function can choose, by using which, if its going to be a lyric, or using my example in the script, a joke. so instead of creating 3 functions, i just have the one. the 3 functions being one that gets called on when a new personal message is displayed that chooses either joke or lyric(which would be the which statement), and one for each, the lyric and joke.  I want it to choose between a lyric and a joke each time that the script requests a new psm, and doing it outside of my function would not allow me to do so..

Anyways, I am only using the lyric method for now, I only have the which variable included for the future, if I decide to use that as well.

You keep on updating your post, lol..   
quote:
And you call that function (GetAllLyrics()) each time the user changes the script preferences (which I assume is what which eventually will reflect).

No, I didnt plan on having the which variable user defined.. thats why it is set up like it is..

Anyways, I had a question. Where you have
quote:
// EXAMPLE START (get 20 lyrics)
        arrLyrics = GetAllLyrics();
        for (var i=0; i<20; i++) {
                Debug.Trace('New lyric: ' + GetRandomLyric());
        }
// EXAMPLE END
Does that go inside my personalMessage function, or outside it like everything else?

This is what the script debugging shows
code:
New lyric: A
New lyric: B
New lyric: E
New lyric: J
New lyric: D
New lyric: K
New lyric: Q
New lyric: R
New lyric: N
New lyric: O
New lyric: G
New lyric: I
New lyric: M
New lyric: S
New lyric: P
New lyric: H
New lyric: U
New lyric: X
New lyric: W
New lyric: C
arrLyrics - F,L,T,V,Y,Z,A,B,E,J,D,K,Q,R,N,O,G
arrPrevios: I,M,S,P,H,U,X,W,C
I added two more trace routines to show the arrays also.
07-05-2007 01:55 AM
Profile E-Mail PM Web Find Quote Report
CookieRevised
Elite Member
*****

Avatar

Posts: 15519
Reputation: 173
– / Male / Flag
Joined: Jul 2003
Status: Away
RE: Random numbers, prevent from being used more than once
quote:
Originally posted by stu
Ok, so if I was to do it as you suggest, outside my personalMessage function I would check to see what which is.. But thats not how I want the script to work though. The reason the which statement is there, is for when the script calls the personalMessage function to get a new personal message, the function can choose, by using which, if its going to be a lyric, or using my example in the script, a joke. so instead of creating 3 functions, i just have the one.
No, what I suggest is exactly how you want your script to work...

What you do now is exactly the same as using 3 functions, only you grouped them together into a 'parent' function. So, that isn't putting 3 functions into 1, that is just grouping 3 functions...

You're really making it difficult for yourself in the way you do it now ;)

quote:
Originally posted by stu
I want it to choose between a lyric and a joke each time that the script requests a new psm, and doing it outside of my function would not allow me to do so..
in that case you do not need the which checking, seperate arrays, and all that other stuff at all. Just concat the lyrics array with your quotes array and be done with it. In other words, you're REALLY making it WAY hard on yourself :P...

(and hence my initial suggestion to not alter my example routine at all but instead optimizing your code!).



-------------------

In a nutshell you would have:
code:
var Text = new Array(); // build in array or whatever... though I would indeed never ever build in a big array like that!
Text[0] = "blah1";
Text[1] = "blah2";

var arrLyrics = new Array(); // Working array
var arrPrevious = new Array(); // working array
var nUniqueness = 10; // magic


function GetAllLyrics(nWhich) {
        arrPrevious = new Array();
        switch (nWhich) {
                // use the external file quotes
                case 0: return FileToArray("C:\\quotes.txt")
                // use the internal lyrics
                case 1: return Text
                // use both
                case 2: return FileToArray("C:\\quotes.txt").concat(Text)
       
        }
}


function personalMessage() {
        Debug.Trace ("Started Personal Message");
        if (randomlyric==1) {
                var rndLyric = GetRandomLyric();
                Messenger.MyPersonalMessage = "( 8)" + rndLyric;       
                MsgPlus.DisplayToast("New Random Lyric", "( 8)" + rndLyric, null, 'OnToastClick', null);
                MsgPlus.AddTimer('randomtext', timer);
                Debug.Trace ("Printed personal message - " + rndLyric);
       }
}

function GetRandomLyric() {
etc...
etc...

Which is extremely shorter than what you have now....

GetAllLyrics() is called wherever you have your routine when the user changes the option from "quotes" to "lyrics" or to "both"....

And if you never want to implement a feature where the user can choose from which arrays the random line should be taken, you could simply only use case 2 from GetAllLyrics(). Aka: concatenate all the arrays you're going to use FIRST. Once that is done you don't need to be bothered about stuff like if (which = x) or whatever else...

----------------------------------

quote:
Originally posted by stu
Anyways, I had a question. Where you have
quote:
// EXAMPLE START (get 20 lyrics)
        arrLyrics = GetAllLyrics();
        for (var i=0; i<20; i++) {
                Debug.Trace('New lyric: ' + GetRandomLyric());
        }
// EXAMPLE END
Does that go inside my personalMessage function, or outside it like everything else?
That is example code. Code to show how you would use the above functions...

This post was edited on 07-05-2007 at 02:26 AM by CookieRevised.
.-= A 'frrrrrrrituurrr' for Wacky =-.
07-05-2007 02:00 AM
Profile PM Find Quote Report
stu
Junior Member
**

Avatar
Stu

Posts: 82
Reputation: 1
38 / Male / Flag
Joined: Sep 2004
O.P. RE: Random numbers, prevent from being used more than once
Ok, Im not too worried about the which statement right now, its just redundant code in my script for right now, and I have actually just taken it out, I probably wont use it, but I was playing around with it earlier. But anyways, I still cant seem to get this to work.. all I am still getting is "undefined" for my lyric.. I have ttried putting your code straight in, and playing around with it, cant seem to get it. Havent tried anyeverything, but maybe you've got an idea to speed up the process?

quote:
in that case you do not need the which checking, seperate arrays, and all that other stuff at all. Just concat the lyrics array with your quotes array and be done with it. In other words, you're REALLY making it WAY hard on yourself ...

(and hence my initial suggestion to not alter my example routine at all but instead optimizing your code!).
Yes, I could very well do that, and the reason I did not was that if, going by my example again, I used lyrics, and jokes, they would be displayed different, by adding (8) in front of the lyric, and probably not adding anything to the joke. If i just had them all together, the jokes would also have (8) in front of them.. that is why they are seperate...

Also, I did try to change my initial code to match yours, but as far as I got it didnt work, and then you said something about using my code that I had already, so I changed it all back, lol. I think I am running around in circles.

quote:
That is example code. Code to show how you would use the above functions...
Yes, I realize that is just example code, I was just trying to clarify if that would go inside my function or not, because it did not seem so when you originally posted it.

This post was edited on 07-05-2007 at 02:34 AM by stu.
07-05-2007 02:18 AM
Profile E-Mail PM Web Find Quote Report
Pages: (4): « First « 1 [ 2 ] 3 4 » Last »
« Next Oldest Return to Top Next Newest »


Threaded Mode | Linear Mode
View a Printable Version
Send this Thread to a Friend
Subscribe | Add to Favorites
Rate This Thread:

Forum Jump:

Forum Rules:
You cannot post new threads
You cannot post replies
You cannot post attachments
You can edit your posts
HTML is Off
myCode is On
Smilies are On
[img] Code is On