Better "Randomization" with Simplexml and PHP - php

I'm working on a 'thought' function for a game i'm working on -- it pulls random strings from an XML file, combines them and makes them 'funny'. However, i'm running into a small issue in that the same couple of items keep getting selected each time.
The two functions I am using are
function randRoller($number)
{
mt_srand((microtime()*time())/3.145);
$x = [];
for($i = 0; $i < 100; $i++)
{
#$x = mt_rand(0,$number);
}
return mt_rand(0,$number);
}
/* RETRIEVE ALL RELEVANT DATA FROM THE XML FILE */
function retrieveFromXML($node)
{
$node = strtolower($node);
$output = [];
$n = substr($node,0,4);
#echo $node;
foreach($this->xml->$node->$n as $data)
{
$output[] = $data->attributes();
}
$count = count($output)-1;
$number = $this->randRoller($count);
return $output[$number];
}
Granted, the "randRoller" function is sorta defunct now because the orginal version I had (Which 'rolled' ten numbers from the count, and then selected the one which got the most number of dice) didn't work as planned.
I've tried everything i can think of to get better results && have googled my brains out to fix it. but still am getting the same repetitive results.

Don't use mt_srand() unless you know what you are doing, since it is called automatically. See the note on http://php.net/manual/en/function.mt-srand.php:
Note: There is no need to seed the random number generator with srand() or mt_srand() as this is done automatically.
Remove (all) the mt_srand() call(s).

Related

n factorial issue with large number

I have written the following code for finding n!. I am running this through CLI.
<?php
$handle = fopen("php://stdin", "r");
$number = (int) trim(fgets($handle));
$fact = calcFactorial($number);
echo $fact . "\n";
function calcFactorial($number) {
if ($number < 2) {
return 1;
} else {
return $number * calcFactorial($number - 1);
}
}
fclose($handle);
?>
The above code is working fine. But there are two issues with two different PHP installations.
On one PC I get,
Fatal error: Maximum function nesting level of '100' reached,
aborting!
To correct above problem I find the solution here. Is this the correct way to have a solution? Because it depends on a particular Default Value of 'xdebug.max_nesting_level' .
On other PC I get,
INF
So what is the best approach to tackle this issue?
P.S.: I have gone through various solutions throughout this website but I am not able to conclude.
UPDATE: There is one function suggested. But can it be done without using any kind of function?
Nesting limit:
if the calcFactorial() can by non-recursive then you can change it to this:
function calcFactorial($number){
if($number<2){
return 1;
}
$ret = 1;
for($i=2;$i<=$number;$i++){
$ret = $ret*$i;
}
return $ret;
}
if has to be recursive you never be able to calc factorial of number bigger then Maximum function nesting level.
INF:
That means PHP thinks number is infinitive (to big to store in memory) ... i think (not sure) that answer is bigger than PHP_INT_MAX ...
You can confirm this by echo is_infinite($number);
you can try solve this with storing numbers as strings (of digits) or arrays (of digits) and than write some function to make multiplication of this strings (arrays) but it is not easy to do

Can I retry file_get_contents() until it opens a stream?

I am using PHP to get the contents of an API. The problem is, sometimes that API just sends back a 502 Bad Gateway error and the PHP code can’t parse the JSON and set the variables correctly. Is there some way I can keep trying until it works?
This is not an easy question because PHP is a synchronous language by default.
You could do this:
$a = false;
$i = 0;
while($a == false && $i < 10)
{
$a = file_get_contents($path);
$i++;
usleep(10);
}
$result = json_decode($a);
Adding usleep(10) allows your server not to get on his knees each time the API will be unavailable. And your function will give up after 10 attempts, which prevents it to freeze completely in case of long unavailability.
Since you didn't provide any code it's kind of hard to help you. But here is one way to do it.
$data = null;
while(!$data) {
$json = file_get_contents($url);
$data = json_decode($json); // Will return false if not valid JSON
}
// While loop won't stop until JSON was valid and $data contains an object
var_dump($data);
I suggest you throw some sort of increment variable in there to stop attempting after X scripts.
Based on your comment, here is what I would do:
You have a PHP script that makes the API call and, if successful, records the price and when that price was acquired
You put that script in a cronjob/scheduled task that runs every 10 minutes.
Your PHP view pulls the most recent price from the database and uses that for whatever display/calculations it needs. If pertinent, also show the date/time that price was captured
The other answers suggest doing a loop. A combo approach probably works best here: in your script, put in a few loops just in case the interface is down for a short blip. If it's not up after say a minute, use the old value until your next try.
A loop can solve this problem, but so can a recursive function like this one:
function file_get_contents_retry($url, $attemptsRemaining=3) {
$content = file_get_contents($url);
$attemptsRemaining--;
if( empty($content) && $attemptsRemaining > 0 ) {
return file_get_contents_retry($url, $attemptsRemaining);
}
return $content;
}
// Usage:
$retryAttempts = 6; // Default is 3.
echo file_get_contents_retry("http://google.com", $retryAttempts);

How do I implement this random number generator above every comment in WordPress?

I have a random number generator here, but I can't get it working above all WordPress comments. I get:
Fatal error: Cannot redeclare class Random in [mysite]/functions.php on line 148
Here is the function for the random number generator:
/**
* Generate random images for the forum games function
*/
function random_forum_games() {
class Random {
// random seed
private static $RSeed = 0;
// set seed
public static function seed($s = 0) {
self::$RSeed = abs(intval($s)) % 9999999 + 1;
self::num();
}
// generate random number
public static function num($min = 0, $max = 9999999) {
if (self::$RSeed == 0) self::seed(mt_rand());
self::$RSeed = (self::$RSeed * 125) % 2796203;
return self::$RSeed % ($max - $min + 1) + $min;
}
}
// set seed
Random::seed(42);
// echo 10 numbers between 1 and 10
for ($i = 0; $i < 1; $i++) {
echo Random::num(1, 10) . '<br />';
}
}
add_action( 'forum_games', 'random_forum_games' );
In order to call the function above every comment, in my comments template, I have:
<?php do_action ( 'forum_games' ); ?>
I know why what I am doing is wrong, but I am not really a "programmer". I came here for a little bit of simple help, whether it be a single line of code or a link to something that can tell me what to do without trying to teach me PHP. I do not have time to learn PHP, so please be kind. If there is not a simple solution, then you don't have to answer.
I don't mean to sound defensive, but I have been turned away by programmers before. Not everyone who needs to get something running has the time or skill to learn every single detail. You don't expect every person who prepares a meal for their family to learn how to hunt or to make pesticides, so please do not turn me away just because I cannot do PHP. If you want, just link me to something that isn't trying to teach me to code from scratch. I am doing as much of the work myself as I can, and I'm asking only for tidbits of support, so please don't be rude. Thank you.
You do not define a class inside a function. It should be defined OUTSIDE of the function, and then you can (if need be) INSTANTIATE it inside the function, e.g.
class rand {
...
}
function get_rand() {
$r = new rand();
}
or better yet, you would simply have a get_rand() method inside the class:
class rand() {
function get_rand() {
...
}
}
$r = new rand();
echo $r->get_rand();
it seems like you declared the function more than once. Maybe it is included more than once or you are calling the class more than once. Try moving the class out of the function and if it is in an include file, include it only once with include_once rather than include.
As for people not being friendly... some are, so what. Most are friendly, helpful... just make sure you give details about your problem (code + way to make it repeatable) and show you made an effort, you'll be fine :)

Finding first possibility

If I have this pattern to build ID's:
CX00 where the 0's are replaceable with just a number.. but the following is already in use:
- CX00
- CX02
- CX04
- CX05
- CX07
- CX10
- CX11
- CX12
How can I easily find, either via PHP or MySQL the values CX01, CX03, CX06, CX08, CX09, CX13+ as available values?
I don't know how your data is stored, so I'll leave getting the IDs in an array. Once you do, this will find the next available one.
<?php
function make_id($n) {
$out = 'CX';
if ($n < 10) $out .= '0';
return $out . $n;
}
// Get these from some source
$items = array('CX00', 'CX02', 'CX04', 'CX05');
$id = make_id(0);
for($i=0; in_array($id, $items); $i++)
$id = make_id($i);
echo $id;
?>
This is called a brute-force method, and if you have a lot of IDs there are probably more efficient ways. With 100 maximum, there shouldn't be any problems.
In php simply count up through the ids using a for loop until you have found enough of the unused ids... how many total ids do you expect to have?

How to map (large) integer on (small in size( alphanumeric string with PHP? (Cantor?)

I can't figure out how to optimally do the following in PHP:
In a database, I have messages with a unique ID, like 19041985. Now, I want to refer to these messages in a short-url service but not using generated hashes but by simply 'calculate' the original ID.
In other words, for example: http://short.url/sYsn7 should let me calculate the message ID the visitor would like to request.
To make it more obvious, I wrote the following in PHP to generate these 'alphanumeric ID versions' and of course, the other way around will let me calculate the original message ID.
The question is: Is this the optimal way of doing this? I hardly think so, but can't think of anything else.
$alphanumString = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_';
for($i=0;$i < strlen($alphanumString);$i++)
{
$alphanumArray[$i] = substr($alphanumString,$i,1);
}
$id = 19041985;
$out = '';
for($i=0;$i < strlen($id);$i++) {
if(isset($alphanumString["".substr($id,$i,2).""]) && strlen($alphanumString["".substr($id,$i,2).""]) > 0) {
$out.=$alphanumString["".substr($id,$i,2).""];
} else {
$out.=$alphanumString["".substr($id,$i,1).""];
$out.=$alphanumString["".substr($id,($i+1),1).""];
}
$i++;
}
print $out;
echo trim(base64_encode(pack("L", 19041987)), "=");
print_r(unpack("L", base64_decode("w44iAQ")));
Pack changes the number into four bytes, which is very short but unreadable.
Base64_encode changes the four bytes into some more human-readable characters.
It appends some = characters, which are not needed.
If you do base64_encode(19041987), you get the encoding for the string "19041987", which is not shorter.
You should never use a function inside a for statement since it's played during every loop.
For instance your
for($i=0;$i < strlen($alphanumString);$i++)
{
$alphanumArray[$i] = substr($alphanumString,$i,1);
}
should be
var $alphaLength = strlen($alphanumString);
for($i=0;$i < $alphaLength;$i++)
{
$alphanumArray[$i] = substr($alphanumString,$i,1);
}

Categories