Forum Moderators: coopster

Message Too Old, No Replies

random

         

Simone100

10:25 pm on Sep 17, 2007 (gmt 0)

10+ Year Member



Hello, I've looked at this inside and out to figure out how do a random twice so that it has a much less likely chance to show the same item twice in a row. But rand(1,3) doesn't seems to let you put variables in them $, only numbers. Can anyone help me figure out how to make this a lot less likely to show two items in a row when items are picked randomly? I even tried this below, and if two numbers are the same then it shows the higher numbers, but if they are not the same then they show one of the first calls for the random items. Thing is, if they are not the same and it shows the first calls for a random number, its back to the same problem again of showing too many same items again. Anyone know of some easier and more effective ways of doing this? Thank you very much.


function test(){
$text = Array();
$text= "test1";
$text[2] = "test2";
$text[3] = "test3";
$text[4] = "test4";
$text[5] = "test5";
$text[6] = "test6";
$one = $text[rand(1,3)];
$two = $text[rand(1,3)];
$five = $text[rand(4,6)];
if ($one == $two)
echo $five;
else
echo $one;}
test();
?>

[1][edited by: Simone100 at 10:27 pm (utc) on Sep. 17, 2007]

omoutop

6:25 am on Sep 18, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



rand() takes only intergers rand() [gr2.php.net]

one solution to your problem:
create a table with an autoincreased id, and store there your items. Make sure that these are also unique.

then use rand() with your ids from that table and then extract the corresponding values from the ids

jatar_k

12:14 pm on Sep 18, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



in a small set the number of times you get the same answer will obviously increase with the number of times it is viewed, over time giving each equal exposure

If you don't want repetition then only show a single item in a small set

whoisgregg

3:45 pm on Sep 18, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



You just want to show a single random item from six different text strings?


function randomString($array){
shuffle($array);
return $array[0];
}
$text_array = array('test1','test2','test3','test4','test5','test6');
echo randomString($text_array);

Or do you want to show two or three items from that array without duplication on a single page?


function randomString(&$array, $destructive = false){
if(!is_array($array) ¦¦ count($array) <= 0) return false;
shuffle($array);
$return = $array[0];
if($destructive) unset($array[0]);
return $return;
}
$text_array = array('test1','test2','test3','test4','test5','test6');
echo randomString($text_array, true);
echo randomString($text_array, true);
echo randomString($text_array, true);
// print_r($text_array); // shows the remaining unused strings

Simone100

7:57 am on Sep 19, 2007 (gmt 0)

10+ Year Member



Thanks a lot everybody, gregg I really need to keep the array numbered can anything be done with them numbered? But your on the right track of what I need.

$text[1] = "test1";

I need to have one result only from all the lines in the array. One item only picked randomly, no matter how many lines there are. So just "test10" text or whatever else randomly is pulled.

If two items are picked twice in a row rarely is ok, like 1 in 30 times or less. I just don't want the same two items picked in a row often.

On this, its still picking two items in a row too often.

<?php
function randomString($array){
shuffle($array);
return $array[0];
}
$text_array = Array();
$text_array[1] = "test1";
$text_array[2] = "test2";
$text_array[3] = "test3";
$text_array[4] = "test4";
$text_array[5] = "test5";
$text_array[6] = "test6";
$text_array[7] = "test7";
$text_array[8] = "test8";
$text_array[9] = "test9";
$text_array[10] = "test10";
$text_array[11] = "test11";
$text_array[12] = "test12";
$text_array[13] = "test13";
$text_array[14] = "test14";
$text_array[15] = "test15";
echo randomString($text_array);?>

[1][edited by: Simone100 at 8:38 am (utc) on Sep. 19, 2007]

Simone100

9:07 am on Sep 19, 2007 (gmt 0)

10+ Year Member



Or anyway to shuffle it again or use some other rand to shuffle it again somehow? Or anyway to throw something in the shuffle to confuse it, so it causes it to become even more random? Whatever it takes to keep from getting the same item twice in a row too often.

jatar don't know what you mean by this
"If you don't want repetition then only show a single item in a small set"

And an example of the table approach would help. Thank you.

[edited by: Simone100 at 9:37 am (utc) on Sep. 19, 2007]

jatar_k

12:23 pm on Sep 19, 2007 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



as whoisgregg mentioned, it is very hard to tell if you want a single item or multiple items to display

the trouble is, it's random, if you want to control the output and give even exposure to all items then you will need to use more logic and track views etc. It is hard to make random functions conform to some type of pattern.

whoisgregg

1:16 pm on Sep 19, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



So if you only call it once per page, you're trying to keep it from repeating itself from one page view to the next? You'll need to do some kind of session tracking. I tried to put something together but I need to get more coffee first it seems. :/

Simone100

7:27 am on Sep 20, 2007 (gmt 0)

10+ Year Member



Thanks Gregg, yes I only need ONE item pulled from all the items in the whole array randomly every new page load. You don't have to write me anything in a cookie, I can do that. Was just hoping there was a way to make it more random so it didn't pull two of the same items twice in a row so often. I'm going to play around with what I started a little bit more, sure seems like there should be a way. I'll post here what I find out and if anyone thinks of anything as well, please let me know, thanks a bunch.

Simone100

9:39 am on Sep 20, 2007 (gmt 0)

10+ Year Member



Good news is its out there. There are probably lots of other ways to do this but this is the only one I found so far that works. But it still needs a little tweaking, hoping someone can help me tweak it. I don't know why it works yet but it really does, haven't had two numbers twice in a row forever. The only thing I notice that is wrong with it this is it hardly ever chooses test1 or test2.

Anyone know why this picks items a LOT more randomly, and why it doesn't choose to pick the first 2? Once someone can tell me why it works the way it does, then I'll understand how to get it to choose all the numbers occassionally. Thanks a lot.

<?php
function randstring(){
list($usec, $sec) = explode(" ", microtime());
srand((int)($usec*10));
$text = Array();
$text[1] = "test1";
$text[2] = "test2";
$text[3] = "test3";
$text[4] = "test4";
$text[5] = "test5";
$text[6] = "test6";
$text[7] = "test7";
$text[8] = "test8";
$text[9] = "test9";
$text[10] = "test10";
$text[11] = "test11";
$text[12] = "test12";
$text[13] = "test13";
$text[14] = "test14";
$text[15] = "test15";
$rand_value = $text[rand(1,15)];
echo($rand_value."<br>");
}
randstring();
?>

whoisgregg

4:11 pm on Sep 20, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That's actually the problem with random... when humans want "random" they typically really want "no detectable pattern." And, of course, humans are so good at picking out patterns that a computer generated random will have all sorts of repeats and groupings that make the human take notice.

What you want is "random without repeating" and the only way to do that is to create a list of the items, randomize it a few different ways, put it all together then just loop through your "random playlist." Thankfully, that's not too terribly complex. Example:

<?php
session_start();
$text = array();
$text[1] = "test1";
$text[2] = "test2";
$text[3] = "test3";
$text[4] = "test4";
$text[5] = "test5";
function resetRandom(){
global $text;
$random_iterations = 7; // if this is short, you'll get more repetition because repetition can occur whenever the playlist is reset
$text_keys = array_keys($text);
$_SESSION['random'] = array();
$_SESSION['randomInc'] = 0;
for($i=0; $i<$random_iterations; $i++){
shuffle($text_keys);
if(count($_SESSION['random']) >= 1 ){
while($text_keys[0] == $_SESSION['random'][count($_SESSION['random'])-1]){ // make sure we don't end up with duplication within our master playlist
shuffle($text_keys);
}
}
$_SESSION['random'] = array_merge($_SESSION['random'], $text_keys); // 'concatenate' the arrays together
}
}
function echoRandom(){
global $text;
if(!isset($_SESSION['random']) ¦¦!isset($_SESSION['randomInc'])){
resetRandom(); // first time visitor
}
$_SESSION['randomInc']++;
if(!isset($text[$_SESSION['random'][$_SESSION['randomInc']]])){ resetRandom(); }
return $text[$_SESSION['random'][$_SESSION['randomInc']]];
}
echo '<h1>'.echoRandom().'</h1>';
echo '<pre>'; print_r($_SESSION['random']); echo '</pre>';
?>

Simone100

10:53 pm on Sep 20, 2007 (gmt 0)

10+ Year Member



Thanks a whole lot gregg for that, I'll keep it in case I need it. Problem is, doesn't that take cookies so if cookies are cleared I'm dead in the water?

If someone can tell me why this following one works without cookies I'd appreciate it. I'm also looking up its elements to see if I can figure it out.
[1]


<?php
function randstring(){
list($usec, $sec) = explode(" ", microtime());
srand((int)($usec*10));
$text = Array();
$text[1] = "test1";
$text[2] = "test2";
$text[3] = "test3";
$text[4] = "test4";
$text[5] = "test5";
$text[6] = "test6";
$text[7] = "test7";
$text[8] = "test8";
$text[9] = "test9";
$text[10] = "test10";
$text[11] = "test11";
$text[12] = "test12";
$text[13] = "test13";
$text[14] = "test14";
$text[15] = "test15";
$rand_value = $text[rand(1,15)];
echo($rand_value."<br>");
}
randstring();
?>

Simone100

12:33 am on Sep 21, 2007 (gmt 0)

10+ Year Member



Not working the way I need, I see a lot of people manipulating random easier when its an associative array. I'll be reading up on those.

whoisgregg

4:30 pm on Sep 21, 2007 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



The reason why your second function seems to work better is just because it has more elements in the $text array. The more elements you have, the lower the chance of a repeat. Over thousands of iterations, rand and shuffle are both statistically equivalent. (However, shuffle is over 25% faster in my testing.)

It's like the problem of flipping a coin. You can flip a coin ten times in a row and actually get ten heads. It's only when you flip a coin thousands of times will the heads/tails ratio approach 50/50.

Now what are the odds of rolling the same number twice in a row using a six-sided die? Much lower than the odds of getting two heads in a coin flip in a row. Simply because there are more choices.

You'll always have repeats unless you "stack the deck" (so to speak) to not have repeats. And... If you want to make sure that a particular user doesn't see the same thing twice in a row you'll need to do some kind of user tracking. Otherwise, you can prepare a single server side "random" list but since users will come in simultaneously, drawing from the same list means any particular user might end up pulling the same thing twice.

Non-repeating random order: 1, 2, 1, 3, 2, 3, 1, 2
User A gets item #1
User B gets item #2
User A gets item #1 <- repeat
User C gets item #3
User B gets item #2 <- repeat
User C gets item #3 <- repeat

Of course, you can always fall back to a server side or simple random if the user doesn't have cookies enabled. In which case that user will end up with repeats... no way to avoid that completely.

Simone100

11:43 pm on Sep 21, 2007 (gmt 0)

10+ Year Member



Thanks Gregg, I know I'm a rotten coder but it sure seems like you could throw something sort of hitch into the random to make it even more random, I just don't know what it would be.