I wrote a function to get a 2-digit random number for each day, but it should be retrievable.
For example, today's random number is 72, but later I can provide "day and month" and get this 72 again.
This isn't random. This is a hashing function. For a given input, it always returns the same output. The normal name for something like this is a hashing function.
You don't explain why you want to do this. If you ask again, try to include that context. We may suggest alternatives.
function ranDay($day,$month){
If this were a random function, I'd write out the name: randomDay
. If you really must abbreviate, randDay
would be better. However, as I noted earlier, this isn't random. You are just mapping one input to another, so a name like hashDay
would be better. There may be an even better name.
function hashDay($day, $month) {
if ( ! is_numeric($day) || ! is_numeric($month) || 0 > $day || 0 > $month || 12 < $month || 31 < $day ) {
return;
}
I also added additional whitespace for readability.
Since this is only supposed to work for valid day and month values, I added some basic checks. Even with these, it will still allow dates like the 31st of February, but this restricts the range somewhat. I just return an undefined value implicitly, but you could explicitly return null
(which would do the same thing) or do something like throwing an exception. Note that this also handles if the month or day is given as a string (e.g. January) rather than a number.
Handling zero values with different returns than a value of one is possible:
$day++;
With that, a zero and a one will return different values.
$dig1 = intval(substr($pow1,0,1));
$dig2 = intval(substr($pow2,-1));
I'd write out $digit1
and $digit2
.
Also, you don't need the intval
. You immediately use string concatenation on it, which will throw it back into strings. So the only thing that the intval can do is hide bad input from you.
echo $dig1.$dig2;
Rather than echoing the result, it would probably be better to return
it. That way you can display it or check for invalid values or whatever. This can also be seen as a violation of the Single Responsibility Principle: you are calculating the hash value; don't display it as well. If you really want to display it, consider changing the name to something like printDayHash
.
return $digit1 . $digit2;
Your function will have collisions. There are only 100 possible results, but there are at least 366 valid day/month combinations. Running it on all 416 allowed day/month combinations (including zero values and weird dates like the 31st of February) shows that some results are more likely than others. For example, 91 and 92 (and eight others) are never returned while 16 is returned a whopping twenty times. For most uses, it would be better for this to be more evenly distributed.
My test code:
$count_of = array();
for ( $i = 0; $i < 10; $i++ ) {
for ( $j = 0; $j < 10; $j++ ) {
$count_of[$i.$j] = 0;
}
}
for ( $m = 0; $m <= 12; $m++ ) {
for ( $d = 0; $d <= 31; $d++ ) {
$count_of[hashDay($d, $m)]++;
}
}
asort($count_of);
print_r($count_of);
Note how returning the value rather than displaying it makes this test much easier.