Repeatable random numbers in PHP

  • Thread starter Thread starter GilesGuthrie
  • 5 comments
  • 1,701 views

GilesGuthrie

Staff Emeritus
Messages
11,038
United Kingdom
Edinburgh, UK
Messages
CMDRTheDarkLord
I have a fairly simple problem, but my addled brain can't see a way out of it.

I'm coding a "photo of the day" function. I therefore want the function to choose a random number, but bind it to something, so the number only changes every 24hrs. The number needs to be between zero and the number of rows in a database table (minus one, obviously). There are currently 79 rows in the database.

It is very important to me that the function should not select consecutive row numbers on consecutive days.

I'd rather not have to put a state table into the database, but if none of you guys can come up with a wizard wheeze for this, then that's my out.

Any thoughts?
 
It's possible to do this without saving state if you make the function return the same result for a given day. That way you can have it recursively call itself to make sure you don't select a picture that was selected before.

If that's not what you're after (or too difficult), just add an extra date/time field in your photo table that gets updated when a photo is selected as photo of the day. In the query you can then select for pictures that haven't been selected for 'n' number of days or something like that. It's also very easy to add a check in that same query for the previous record not being selected the day before.
 
This is actually pretty straightforward if it weren't for the "no consecutive rows on consecutive days" requirement. The general idea is to generate a unique number from the day/date then use that to seed the random number generator. First we see what yesterday's number was, then keep generating numbers until we got a number for today that is not yesterday's number plus one. Something along the lines of:

Code:
$unixtime = time();
$seed = $unixtime - ( $unixtime % 86400 ); // 86400 = number of seconds in a day
srand( $seed - 86400 ); // see what yesterday's row number was
$row_yesterday = rand( 1, 79 );
srand( $seed );
do
{
    $row_today = rand( 1, 79 );
} while ( $row_today == $row_yesterday + 1 );

This may not work, of course, if yesterday had to be adjusted because of the number two days ago. And if you add checks for that, you have to worry about three days ago, etc, ad infinitum. But if you can live with consecutive rows happening on average only every 6241 or so days, then this should work fine.
 
Cool, thanks for that. I'll do some modelling on it later and let you know how I get on.
 
For purposes of testing only, you can change the 86400 to another value; if you change it to 3600 in both places that it occurs, the "daily" seed will change once per hour. Make it 600 and it'll change every ten minutes, 60 would be once a minute, etc.
 
So with BobK's code, and a snippet for image resizing that I got from php.net, my POTD application is running nicely. Much :) and thanks.
 
Back