Calculating Odds Throttles in PHP - php

In PHP, if I build a factory inspection program with a conveyor belt where the popdown listbox on the form is 100% (inspect nothing -- let all go through) to 0% (inspect everything), what is the function to calculate when one of the widgets is due for inspection?
A little extra info -- the label says "Let [x%] widgets go through without inspection".
More than this, how can we test your algorithm to prove it's correct? For instance, a value of 100%, run 99999 times, should show no inspections. A value of 99%, run 99999 times, should maybe show one inspection in a blue moon if run repeatedly. A value of 0%, run 99999 times, should show all 99999 widgets being sent to inspection.
EDIT: A coworker says I'm getting odds and probability mixed up here. She thinks I'm describing probability?
Anyway, I tried this code as a test, but it doesn't do anything except at the 100, and 50 through 1 marks. However, the 1-49 act like the 50, while the 51 through 100 act like 100.
<?php
$nChance = # $argv[1];
$nChance = intval($nChance);
for ($i = 1; $i <= 999999; $i++) {
$nTest = rand(1,floor(100/$nChance));
if (!($nTest == 1)) {
die("INSPECT! i($i) rand($nTest) chance($nChance)\n");
}
}
I then tried this variation and that failed too because it simply said INSPECT all the time.
<?php
$nChance = # $argv[1];
$nChance = intval($nChance);
for ($i = 1; $i <= 999999; $i++) {
$nTest = rand(0,100);
if (!($nTest < $nChance)) {
die("INSPECT! i($i) rand($nTest) chance($nChance)\n");
}
}

$nChance = 5; // % chance of inspection
$x = 1; // number of seconds between products passing inspection point
while ( isLineRunning() )
{
if( mt_rand(1,100) <= $nChance )
{
echo "INSPECT ITEM!";
}
sleep( $x );
};
this would check every 'x' seconds while the line is running.
Your colleague is kind of correct but for your purposes you are making a decision based on whether a random number is less than or equal to (in this case) 5 which if truly random (which its not when generated like this) should deliver a 1 in 20 chance you select any given item.

Related

PHP - Changing Value by a small market percentage

First post, please be gentle.
I'm trying to create a simple market script where for example I have a number in my database ie 50.00 and I want to run a cron job php script to increase or decrease this randomly to a minimum of 10.00 and a maximum of 75.00.
I thought a random 0,1 follow by 2 if statements 1 rand(-0.01,0.05) if 2 rand(0.01,0.05) then $sql = "UPDATE price SET oil='RESULT'";
I've tried a few times at the above but I can't get it to run and the other crons in the file work.
<?php
//Get Oil Price from database
$oilchange = rand(1, 2);
if ($oilchange == '1') {
$oilnew = rand(0.01,0.05);
//Oil price from database times oil new.
} else {
$oilnew = rand(-0.01,-0.05);
//Oil price from database times oil new.
}
// Update Price
?>
Rand is for integers (whole numbers)
First up, your use of rand between two decimal values (called floats) won't work, as rand is for integers only. So, you'd first want to have a random function which does output floats, like this:
function randomFloat($min = 0, $max = 1) {
return $min + mt_rand() / mt_getrandmax() * ($max - $min);
}
Then we can safely use it between, say, 1% and 5%:
$percentSwing = randomFloat(0.01, 0.05);
Rand defaults to being 0 or 1. We can use that to randomly invert it, so we also cover -1% to -5%:
$percentSwing *= rand() ? 1 : -1;
The above could also be written like this:
if(rand() == 1){
// Do nothing:
$percentSwing *= 1;
}else{
// Invert it:
$percentSwing *= -1;
}
So, we now know how much we need to swing the number by. Let's say it was $oilPrice:
$oilPrice = 48;
We can just multiply the percent swing by that number to get the amount it's changing by, then add it back on:
$oilPrice += $percentSwing * $oilPrice;
So far so good! Now we need to make sure the price did not go out of our fixed range of 10 to 75. Assuming you want to 'clamp' the number - that means if it goes below 10, it's set at 10 and vice-versa, that's done like this:
if( $oilPrice < 10 ){
// It went below 10 - clamp it:
$oilPrice = 10;
}else if( $oilPrice > 75 ){
// It went above 75 - clamp it:
$oilPrice = 75;
}
The above can also be represented in one line, like this:
$oilPrice = max(10, min(75, $oilPrice));
So, that gives us the whole thing:
function randomFloat($min = 0, $max = 1) {
return $min + mt_rand() / mt_getrandmax() * ($max - $min);
}
// Define the oil price (e.g. pull from your database):
$oilPrice = 48;
// get a random 1% to 5% swing:
$percentSwing = randomFloat(0.01, 0.05);
// Invert it 50% of the time:
$percentSwing *= rand() ? 1 : -1;
// Swing the price now:
$oilPrice += $percentSwing * $oilPrice;
// Clamp it:
$oilPrice = max(10, min(75, $oilPrice));
// Output something!
echo $oilPrice;
As a side note here, money in real financial systems is never stored as a float, because rounding errors can cause major problems.

My PHP array issue

This will be a pretty strange question, but bear with me.
I'm coding a browser based game, and each player has an amount of guards, each with 100 health. Every time they are shot, the guards lose health. If all the guards are dead, the player takes the health instead.
The shot damage always overlaps as well, so if player has 3 guards, and the top guard has 60 health, a shot of 100 will kill guard 3 and leave guard 2 with 60 health.
i use a php array to sort this, and it works, except when it comes down to the players health. It doesn't calculate correctly, eg all a players guards are dead and the player has 60 health left. He is shot for 100, but instead of dying the health loops round so he has some other number health instead of -40.
$p_bg = array(); // players guard count
$p_bg[0] = $rs[bgs_hp2]; // only the top guard hp is saved (bgs_hp2)
$p_hp = $rs[hp2]; // players health
$dmg = 80 // shot damage
$x = 0;
while($x < $rs[BGs2]) { $p_bg[$x] = 100; $x++; }
// As long as there's still damage to take and bgs to take it:
while($dmg && !empty($p_bg)) {
$soak = min($p_bg[0], $dmg); // not more than the first bg can take
$p_bg[0] -= $soak; // remove hps from the first bg
$dmg -= $soak; // deduct from the amount of damage to tage
if ($p_bg[0] == 0) {
// bodyguard dead, remove him from the array
array_shift($p_bg);
}
}
// If there's any damage left over, it goes to hp
$p_hp = $p_hp - $dmg;
Without knowing the contents of $rs or knowing what the constants bgs_hp2, hp2, and BGs2 are, it's hard to say, but it seems like the problem lies around this combination of lines:
$p_bg = array(); // Create an empty array
$p_bg[0] = $rs[bgs_hp2]; // Populate the first index, possibly null?
$x = 0;
while($x < $rs[BGs2]) { $p_bg[$x] = 100; $x++; }
I'd suspect BGs2 is the bodyguard count for the player? It seems that you're setting the top bodyguard's health to 100 each time this code is hit. Maybe it would be more clear if it was rearranged as follows:
$p_bg = array($rs[bgs_hp2]);
for ($x = 0; $x < $rs[BGs2]; $x++) { $p_bg[] = 100; }
Other than that, log out your variables (using print_r($var) or var_dump($var) as necessary) to see the actual data you're executing on. Good luck!

Replace elseifs with math

My question is how could I replace those if's with math formula?
if ($l <= 3500)
{
$min = 100;
}
elseif ($l <= 4000)
{
$min = 120;
}
elseif ($l <= 4500)
{
$min = 140;
}
elseif ($l <= 5000)
{
$min = 160;
}
As you see this is raising 20 for every 500 levels.
As you see this is raising 20 for every 500 levels.
Well, that's your formula right there.
$min = 100 + ceil(($l-3500)/500) * 20;
We start with 100, our base value and add that to the rest of the calculation.
$l starts with 3500 less.
We ceil() the result since we only want to jump when we pass the whole value.
We multiply that by 20.
If we want to address the case where $l is less than 3500 and set 100 as the minimum value, we also need to asset that $l-3500 is more than zero. We can do this as such:
$min = 100 + ceil(max(0,$l-3500)/500) * 20;
How did I get there?
What we're actually doing is plotting a line. Like you said yourself we go a constant amount for every constant amount. We have something called linear progression here.
Great, so we recognized the problem we're facing. We have an imaginary line to plot and we want integer values. What next? Well, let's see where the line starts?
In your case the answer is pretty straightforward.
if ($l <= 3500) {
$min = 100;
}
That's our starting point. So we know the point (3500,100) is on our line. This means the result starts at 100 and the origin starts at 3500.
We know that our formula is in the form of 100+<something>. What is that something?
Like you said, for every 500 levels you're raising 20. So we know we move 20/500 for every 1 level (because well, if we multiply that by 500 we get our original rule). We also know (from before) that we start from 3500.
Now, we might be tempted to use $min = 100 + ($l-3500) * (20/500); and that's almost right. The only problem here is that you only want integer values. This is why we ceil the value of level/500 to only get whole steps.
I tried to keep this with as little math terminology as possible, you can check the wikipedia page if you want things more formal. If you'd like any clarification - let me know
Here is my approach about this problem. It's not better than a single-line formula, but for sake of being modifiable, I generally decide this kind of solutions:
$min = 100;
for($i=3500; $i<=5000; $i+=500)
{
if($l <= $i) break;
$min += 20;
}
//Now $min has got desired value.
You can express the function as follows:
f(x) := a * x + b
The inclination of the line is calculated as:
a := 20 / 500
To find b you need to extrapolate a value that's on the line; in this case, that could be 3500 (x) and 120 (f(x)). That works out to be -40.
So the function has become:
f(x) := (20 / 500) * x - 40
There are two special cases:
Left of 3500 the value of f(x) must remain 100, even though f(x) is less.
The inclination is not continuous but discrete.
Both cases applied:
$min = max(100, ceil($l / 500) * 20 - 40)

Find maximum value of a function using php

How can I get maximum value of a function in specific range with php.
For example I have a function:
function f($x){
return pow($x,2);
}
and i want to get maximum value of this function in range (-1,1).
how can I implement this in php or using some other library?
There's no generic way to do this; you have to do the maths yourself.
Maximisation / Minimisation problems are solved by differentiation. In this case, you would get:
d(x^2)/dx = 2*x
The method for calculating the differential depends on your function. It's not that hard for simple functions like this, and Wolfram Alpha (http://www.wolframalpha.com/) will do it for you if you ask it nicely (http://www.wolframalpha.com/input/?i=d%28x%5E2%29%2Fdx).
Then you set that to 0, which tells you when the gradient is 0 (and therefore, it is at a maximum, minimum, or turning point):
2*x = 0
This tells you that you have a point to check at x = 0 (see the "solution" section here: http://www.wolframalpha.com/input/?i=d%28x%5E2%29%2Fdx%3D0). Now check the value of your function at the lower bound, upper bound, and the point(s) this tells you to check, and get the maximum/minimum of all those results. This will be your limit within that range.
$maximumValue = -999999999;
for ($i = -1; $i <= 1; $i++) {
$maximumValue = max($maximumValue, f($i));
}
var_dump($maximumValue);
..should work fine
This will only check for the numbers -1, 0 and 1. If you want more precision, just change $i++ to eg. $i += 0.1:
$maximumValue = -999999999;
for ($i = -1; $i <= 1; $i += 0.1) {
$maximumValue = max($maximumValue, f($i));
}
var_dump($maximumValue);
This will give you -1, -0.9, -0.8 ..... 0.8, 0.9 and 1.
It could also be changed to $i += 0.000000001 if you want to waste a lot of resources, but get a more accurate result.
If you use differentiation you have to deal with the case that there are no local optima. If the function is smooth this would mean that the optima occur on the endpoints. I am not sure how precise this all needs to be,but perhaps if the function is just given by a finite list of pairs you could sort a list which contains all the points where the function is defined.

Still got negative values even I set already less than or equals to 0

I am creating a PLayer 1 vs Player 2 simple system and the system limit only till 30 rounds if 30 rounds is done and both player are still alive then it is called a draw. If player 1 gets 0 or less than 0 before 30 rounds and player 2 is still alive then player 2 wins the games and etc...
Problem is why I am still having negative values whats wrong with my code? I already set an if statement in there. Any idea will be a big help for me and I am open for improvements since I am still a beginner programmer THANK YOU.
<?php
//Player 1
$p1Health = 100;
$p1Attack = 5;
$p1Speed = 3;
//Player 2
$p2Health = 70;
$p2Attack = 8;
$p2Speed = 5;
//Greater speed attack first
$speed1=0;
$speed2=0;
echo '<td>'.$p1Health.'</td><td>'.$p1Attack.'</td><td>'.$p1Speed.'</td>';
echo '<td>'.$p2Health.'</td><td>'.$p2Attack.'</td><td>'.$p2Speed.'</td>';
//Compare speed
if($p1Speed<$p2Speed){
$speed1=1; //start first
$speed2=0;
}
else {
$speed1=0; //start first
$speed2=1;
}
$rounds = 30; //maximum rounds
$count = 0;
while($count<=30){
if($p1Health<=0 || $p2Health<=0){ //if any of the players health is equal or below zero loop stop and declare winner
break;
}
else if($speed1==1){
$p2Health = $p2Health - $p1Attack;
echo 'Player 2 damaged by '.$p1Attack.' points.Health points left: '.$p2Health.'<br>';
//turn to other player to attack
$speed1=0;
$speed2=1;
}
else if($speed2==1){
$p1Health = $p1Health - $p2Attack;
echo 'Player 1 damaged by '.$p2Attack.' points.Health points left: '.$p1Health.'<br>';
//turn to other player to attack
$speed1=1;
$speed2=0;
}
$count++;
}
if($p1Health>0 && $p2Health<=0){
echo 'Player 1 wins the battle';
}
else if($p2Health>0 && $p1Health<=0){
echo 'Player 2 wins the battle';
}
else if($p1Health>0 && $p2Health>0){
echo 'Battle draw';
}
?>
I don't know if my code is right but this is based for my understanding any idea to improve this will be really a big help for me.
Player 1 starts with 100 health. After each attack from player 2, that goes down by 8. After the 12th attack, player 1 will have 4 health. On the 13th attack, that value is reduced by another 8, yielding −4.
You'll see this phenomenon any time one player's attack strength doesn't evenly divide the other's health.
If you don't want the value to go below zero, even after an attack, then check for that and fix it:
$p1Health = $p1Health - $p2Attack;
if ($p1Health < 0)
$p1Health = 0;
This is because the values can still go negative in, say, execution number 20 of the loop. The loop would still execute again to iteration number 21 where your if conditional would break.
You might consider using the health values in the while condition like:
while ($count < $rounds && p1Health > 0 && p2Health > 0) {
And then eliminate the first conditional in the loop that checks for health values.

Categories