How can I solve this number doubling and halving problem? - php

I feel kind of dumb for asking this but I can't figure out this code challenge. I have to initialize a number with a value of one. Then I have to double this number till it's higher than 1000. After which it will be halved until it reaches 1 again, vice versa.
This is what I have so far. Obviously, it doesn't work as once it goes over 1000 and gets halved it will meet the requirement to get doubled again. I feel pretty stupid for not seeing the solution. Any help would be appreciated.
session_start();
$getal = 1;
if(isset($_SESSION['getal'])){
if($_SESSION['getal'] <= 1000){
$_SESSION['getal'] *= 2;
}elseif ($_SESSION['getal'] > 1000){
$_SESSION['getal'] *= 0.5;
}
}
else{
$_SESSION['getal'] = $getal;
}

You need to keep a "direction" in session.
Keep the multiplier to 2 until the value 1000 is reached.
Then, change the multipler to .5 until you reach the value 1 (or less than 2).
session_start();
$getal = 1;
if (isset($_SESSION['getal'])) {
if ($_SESSION['mult'] > 1 && $_SESSION['getal'] >= 1000) {
$_SESSION['mult'] = .5;
}
elseif ($_SESSION['getal'] < 2) {
$_SESSION['mult'] = 2;
}
$_SESSION['getal'] *= $_SESSION['mult'];
}
else{
$_SESSION['getal'] = $getal;
$_SESSION['mult'] = 2;
}

You need to store & check current direction (up/down), working code would be
<?php
session_start();
$getal = 1;
if (!isset($_SESSION['dir'])) {
$_SESSION['dir'] = 'up';
}
if(isset($_SESSION['getal'])){
if ($_SESSION['getal'] <= 1000 && $_SESSION['dir'] === 'up') {
$_SESSION['getal'] *= 2;
$_SESSION['dir'] = 'up';
} else {
$_SESSION['getal'] *= 0.5;
$_SESSION['dir'] = 'down';
if ($_SESSION['getal'] == 1) {
$_SESSION['dir'] = 'up';
}
}
} else {
$_SESSION['getal'] = $getal;
}
echo $_SESSION['getal'];
echo $_SESSION['dir'];

Your code is almost there, you just need to store the number you are multiplying by and check it, and you will be all good.
The basic idea is to store the multiplier as a session variable as well. You will need to change the multiplier whenever you get to 1 or above 1,000. I used a ternary statement to do this, because it is just assigning a variable value (which is what ternaries are for), but an if/then would work just as well.
<?php
session_start();
if (isset($_SESSION['getal'])) {
//the math
$_SESSION['getal'] *= $_SESSION['multiplier'];
//set the multiplier for the next iteration
$_SESSION['multiplier'] = $_SESSION['getal'] > 1000 ? .5 : ($_SESSION['getal'] <= 1 ? 2 : $_SESSION['multiplier']);
}
else {
//initialize
$_SESSION['getal'] = 1;
$_SESSION['multiplier'] = 2;
}
echo $_SESSION['getal'];
?>

Related

PHP if and else statement not working properly

im trying to create a script that generates a number and depending on the number generated it prints something specific but it's not working properly, Heres the code:
<?php
for($zz = 1; $zz <= 20; $zz++) {
$rangen = rand(1,100);
$a = (1 <= 0) && (0 <= 7);
$b = (8 <= 0) && (0 <= 17);
echo ("<br>".$rangen . "<br>");
if($a) {
echo "a";
} elseif ($b) {
echo "b";
} else {
echo "c";
}
}
?>
The error is that it keeps printing "c" no matter what the number is.
If anyone could help that would be great, thanks.
Your conditions are all wrong. Your comparing the same numbers and never using $rangen, this is why you obtain the same result each time.
1 <= 0 and 8 <= 0 will always return false which is why you always go to the else statement.

Any idea for knowing if the certain percent of chance triggers

I have a game development project and I have specific character one of the skill of the character is that it has a 10% chance of doubling its attack.
Question: How can I trigger it?
I hope i understand ure question:
<?php
$random = rand(1,10);
if(($random == 1) || ($random == 2) || ($random == 3))
$value += $value;
?>
Here you have a 30% chance to hit 1, 2 or 3.. and if its hit then your value gets doubled.
Ok now for your Update u just need a 10% chance? But okay:
<?php
$random = rand(1,10);
if($random == 1)
$value += $value;
?>
function doubleHit($percentChance = 30)
{
if (mt_rand(1,100) <= $percentChance) {
return true;
}
return false;
}
var_dump(doubleHit(35)); // will return either true / false
Note that this is only pseudorandom. Also note that this is faster / better than rand().
For example this code will double the value theoretically one in three times? It's hard for me to understand you.
$value = 200;
if (rand(1,3)===1) {
$value*=2;
}
Or maybe this, for percents:
$value = 200;
$percent = 30;
$chance = rand(1, 100);
if ($chance <= $percent) {
$value *= 2;
}

Making many If statments into One statement. Php

function rawtransform{
if ($raw>=500 && $raw<=550){
$score= 1;
}
if ($raw>=550 && $raw<=600){
$score= 2;
}
if ($raw>=600 && $raw<=650){
$score= 3;
}
if ($raw>=700 && $raw<=750){
$score= 4;
}
if ($raw>=750 && $raw<=800){
$score= 5;
}
if ($raw>=800 && $raw<=850){
$score= 6;
}
if ($raw>=850 && $raw<=900){
$score= 7;
}
if ($raw>=900 && $raw<=950){
$score= 8;
}
if ($raw>=950 && $raw<=1000){
$score= 9;
}
}
This seems very basic and not very well coded. (I am only learning php )
Can anyone offer a better way of doing this? maybe a single if statement. I think there is a way just cant get my head round it.
Thanks
How about just using math?
function rawtransform($raw) {
$score = (int)($raw/50)-9;
}
You may want to add a range check for the input, though.
You can create a list of conditions, and loop through the and apply the if.
$conditions = array(
array(500, 550, 1), // greater than value, lesser than value, assignment value
array(550, 600, 2),
array(650, 700, 3) // add the rest of the conditions
);
foreach($conditions as $condition) {
if($raw >= $condition[0] && $raw <= $condition[1]) {
$score = $condition[2];
}
}
if ($raw >= 500 && $raw<= 1000){
$score = ceil(($raw-500)/50);
}
You can use if...else constructs.
if ($raw>=500 && $raw<=550){
$score= 1;
}
elseif ($raw>=550 && $raw<=600){
$score= 2;
}
elseif ($raw>=600 && $raw<=650){
$score= 3;
}
That way, if the script encounters a size of, say, 575 it won't even bother to go through the following conditions.
In your given example, the script can be simplified by:
function rawtransform($raw) { $score = floor(($raw - 450)/50); return $score; }
Your logic seems to be that you are subtracting 450 from raw, then dividing it by 50 and rounding down to the nearest whole number. (There are problems in your implementation however, as if raw is a factor of 50, it will meet the requirements for two of the if statements and there is a condition missing for when it falls between 650 and 700.)
You could do this as follows:
floor(($raw-450)/50)

PHP "Maximum execution time"

I'm trying to program my own Sine function implementation for fun but I keep getting :
Fatal error: Maximum execution time of 30 seconds exceeded
I have a small HTML form where you can enter the "x" value of Sin(x) your looking for and the number of "iterations" you want to calculate (precision of your value), the rest is PhP.
The maths are based of the "Series definition" of Sine on Wikipedia :
--> http://en.wikipedia.org/wiki/Sine#Series_definition
Here's my code :
<?php
function factorial($int) {
if($int<2)return 1;
for($f=2;$int-1>1;$f*=$int--);
return $f;
};
if(isset($_POST["x"]) && isset($_POST["iterations"])) {
$x = $_POST["x"];
$iterations = $_POST["iterations"];
}
else {
$error = "You forgot to enter the 'x' or the number of iterations you want.";
global $error;
}
if(isset($x) && is_numeric($x) && isset($iterations) && is_numeric($iterations)) {
$x = floatval($x);
$iterations = floatval($iterations);
for($i = 0; $i <= ($iterations-1); $i++) {
if($i%2 == 0) {
$operator = 1;
global $operator;
}
else {
$operator = -1;
global $operator;
}
}
for($k = 1; $k <= (($iterations-(1/2))*2); $k+2) {
$k = $k;
global $k;
}
function sinus($x, $iterations) {
if($x == 0 OR ($x%180) == 0) {
return 0;
}
else {
while($iterations != 0) {
$result = $result+(((pow($x, $k))/(factorial($k)))*$operator);
$iterations = $iterations-1;
return $result;
}
}
}
$result = sinus($x, $iterations);
global $result;
}
else if(!isset($x) OR !isset($iterations)) {
$error = "You forgot to enter the 'x' or the number of iterations you want.";
global $error;
}
else if(isset($x) && !is_numeric($x)&& isset($iterations) && is_numeric($iterations)) {
$error = "Not a valid number.";
global $error;
}
?>
My mistake probably comes from an infinite loop at this line :
$result = $result+(((pow($x, $k))/(factorial($k)))*$operator);
but I don't know how to solve the problem.
What I'm tring to do at this line is to calculate :
((pow($x, $k)) / (factorial($k)) + (((pow($x, $k))/(factorial($k)) * ($operator)
iterating :
+ (((pow($x, $k))/(factorial($k)) * $operator)
an "$iterations" amount of times with "$i"'s and "$k"'s values changing accordingly.
I'm really stuck here ! A bit of help would be needed. Thank you in advance !
Btw : The factorial function is not mine. I found it in a PhP.net comment and apparently it's the optimal factorial function.
Why are you computing the 'operator' and power 'k' out side the sinus function.
sin expansion looks like = x - x^2/2! + x^3/3! ....
something like this.
Also remember iteration is integer so apply intval on it and not floatval.
Also study in net how to use global. Anyway you do not need global because your 'operator' and power 'k' computation will be within sinus function.
Best of luck.
That factorial function is hardly optimal—for speed, though it is not bad. At least it does not recurse. It is simple and correct though. The major aspect of the timeout is that you are calling it a lot. One technique for improving its performance is to remember, in a local array, the values for factorial previously computed. Or just compute them all once.
There are many bits of your code which could endure improvement:
This statement:
while($iterations != 0)
What if $iterations is entered as 0.1? Or negative. That would cause an infinite loop. You can make the program more resistant to bad input with
while ($iterations > 0)
The formula for computing a sine uses the odd numbers: 1, 3, 5, 7; not every integer
There are easier ways to compute the alternating sign.
Excess complication of arithmetic expressions.
return $result is within the loop, terminating it early.
Here is a tested, working program which has adjustments for all these issues:
<?php
// precompute the factorial values
global $factorials;
$factorials = array();
foreach (range (0, 170) as $j)
if ($j < 2)
$factorials [$j] = 1;
else $factorials [$j] = $factorials [$j-1] * $j;
function sinus($x, $iterations)
{
global $factorials;
$sign = 1;
for ($j = 1, $result = 0; $j < $iterations * 2; $j += 2)
{
$result += pow($x, $j) / $factorials[$j] * $sign;
$sign = - $sign;
}
return $result;
}
// test program to prove functionality
$pi = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620;
$x_vals = array (0, $pi/4, $pi/2, $pi, $pi * 3/2, 2 * $pi);
foreach ($x_vals as $x)
{
$y = sinus ($x, 20);
echo "sinus($x) = $y\n";
}
?>
Output:
sinus(0) = 0
sinus(0.78539816339745) = 0.70710678118655
sinus(1.5707963267949) = 1
sinus(3.1415926535898) = 3.4586691443274E-16
sinus(4.7123889803847) = -1
sinus(6.2831853071796) = 8.9457384260403E-15
By the way, this executes very quickly: 32 milliseconds for this output.

PHP - Project Euler #2

I got the answer fine, but when I run the following code,
$total = 0;
$x = 0;
for ($i = 1;; $i++)
{
$x = fib($i);
if ($x >= 4000000)
break;
else if ($x % 2 == 0)
$total += $x;
print("fib($i) = ");
print($x);
print(", total = $total");
}
function fib($n)
{
if ($n == 0)
return 0;
else if ($n == 1)
return 1;
else
return fib($n-1) + fib($n-2);
}
I get the warning that I have exceeded the maximum execution time of 30 seconds. Could you give me some pointers on how to improve this algorithm, or pointers on the code itself? The problem is presented here, by the way.
Let's say $i equal to 13. Then $x = fib(13)
Now in the next iteration, $i is equal to 14, and $x = fib(14)
Now, in the next iteration, $i = 15, so we must calculate $x. And $x must be equal to fib(15). Now, wat would be the cheapest way to calculate $x?
(I'm trying not to give the answer away, since that would ruin the puzzle)
Try this, add caching in fib
<?
$total = 0;
$x = 0;
for ($i = 1;; $i++) {
$x = fib($i);
if ($x >= 4000000) break;
else if ($x % 2 == 0) $total += $x;
print("fib($i) = ");
print($x);
print(", total = $total\n");
}
function fib($n) {
static $cache = array();
if (isset($cache[$n])) return $cache[$n];
if ($n == 0) return 0;
else if ($n == 1) return 1;
else {
$ret = fib($n-1) + fib($n-2);
$cache[$n] = $ret;
return $ret;
}
}
Time:
real 0m0.049s
user 0m0.027s
sys 0m0.013s
You'd be better served storing the running total and printing it at the end of your algorithm.
You could also streamline your fib($n) function like this:
function fib($n)
{
if($n>1)
return fib($n-1) + fib($n-2);
else
return 0;
}
That would reduce the number of conditions you'd need to go through considerably.
** Edited now that I re-read the question **
If you really want to print as you go, use the output buffer. at the start use:
ob_start();
and after all execution, use
ob_flush();
flush();
also you can increase your timeout with
set_time_limit(300); //the value is seconds... so this is 5 minutes.

Categories