Why does my PHP-script end in a loop? - php

I wrote a simple PHP scripts which should print 320 random generated ages. These ages should be generated in pairs, and the difference between the ages should be calculated. I wrote the following code, everything but the getDifference function works. If I leave the function out, 320 ages will be generated.
But if I leave the function in it:
1) Doesn't work right
2) Stays in a long loop
3) Sometimes prints out
4 ages instead of the 320.
I need some help.
<?php
//Minimum of the age range.
$min = 8;
//Maxium of the age range.
$max = 25;
//Generating the ages
for ($i=0;$i<160;$i++) {
$age1= random_float($min,$max);
$firstage= round($age1,1);
$age2= random_float($min,$max);
$secondage=round($age2,1);
$diff = getDifference ($age1, $age2);
print "Age 1: $firstage Age 2: $secondage Difference: $diff \n ";
}
//Function to generate a random float number
function random_float ($min,$max) {
return ($min+lcg_value()*(abs($max-$min)));
}
// Function to calculate the differences between the ages in years and months
function getDifference ($age1, $age2) {
$difference = abs($age2 - $age1);
$jaar = 0;
$newdifference = round($difference,1) * 12;
for ($newdifference; $newdifference >=12; $newdifference -12) {
$jaar ++; }
$month = $newdifference - 12*$jaar;
$newmonth = floor($month);
$test = "$jaar years and $newmonth months";
return $test;
}
?>

In this loop:
for ($newdifference; $newdifference >=12; $newdifference -12) {
$jaar ++;
}
Two things:
First, you don't need that first loop condition statement. The variable already exists, there's nothing to declare:
for (; $newdifference >=12; $newdifference -12) {
$jaar ++;
}
Second, you never modify $newdifference within the loop. Basically, that third loop condition statement ($newdifference -12) doesn't actually do anything. It subtracts 12, but doesn't do anything with the result of that subtraction. So if the loop begins (because the condition is true), then it will never end (because the condition will always be true). Perhaps you meant to modify the value in that last loop condition statement?:
for (; $newdifference >=12; $newdifference -= 12) {
$jaar ++;
}

It's stuck in a loop because you're not incrementing your $i inside your for loop:
Replace:
for ($newdifference; $newdifference >=12; $newdifference -12)
By:
for ($newdifference; $newdifference >=12; $newdifference -= 12)
You need to use the -= instead of the - because otherwise it's not updating the value of $newdifference, it's just returning the result of the equation.

You're not changing $newdifference at all. Your for loop should be
for($newdifference; $newdifference >= 12; $newdifference -= 12) {
This will decrement $newdifference by 12.

Related

Exam Qn: Convert do while loop to for loop (PHP)

Recently, my exams got over. My last exam was based on PHP. I got the following question for my exam:
"Convert the following script using for loop without affecting the output:-"
<?php
//Convert into for loop
$x = 0;
$count = 10;
do
{
echo ($count. "<BR>");
$count = $count - 2;
$x = $x + $count;
}
while($count < 1)
echo ($x);
?>
Please help me as my computer sir is out of station and I am really puzzled by it.
Well, If I understand well, You have to use "for" loop, instead of "do...while", but the printed text must not change.
Try:
$count = 10;
$x = 0;
$firstRun = true;
for(; $count > 1 || $firstRun;) {
$firstRun = false;
echo ($count . "<BR>");
$count -= 2;
$x = $x + $count;
}
echo ($x);
By the way loop is unnecessary, because $count will be greater than 1 after the first loop, so the while will get false.
EDIT
$firstRun to avoid infiniteLoop
$count in loop
EDIT
Fixed code for new requirement
Removed unnecessary code
Hmmm I don't know if your teacher wanted to own you... but the do{} will execute only once since $count is never < 1.
The output of your teacher's code is:
10
8
I presume there was a mistake in the code and the while would be while($count > 1) which would make more sense (since it's weird to ask for a loop to output only 10 8) and would result in this output:
10
8
6
4
2
20
Then a good for() loop would have been :
$x = 0;
$count = 10;
for($i = $count; $i > 1; $i -= 2)
{
$count -= 2;
echo $i . "<br>";
$x += $count;
}
echo $x;
Which will output the same values.
If you can, ask your teacher for this, and comment the answer ^^ ahahah

Finding the averege in a loop counting to 100

I need to find the averege after using a loop counting ever 3rd to a 100. The loop part is easy enough, but I need to sum every value then divide the sum on the total of values.
for ($x = 3; $x < 100; $x+=3) {
echo $x.", ";
}
This is the loop I need to use. How to I sum the values this produces and how do I find how many values this loop produces?
I believe the intention here is to learn about loops, otherwise this stuff can be done without looping too.
For learning purpose, you can simply introduce two variables count and sum and compute them inside the loop. For count, you just increment it on each iteration. For sum, you add the current value of x into sum. After the loop you print both variables.
$count = 0;
$sum = 0;
for ($x = 3; $x < 100; $x+=3) {
echo $x.", ";
$count++;
$sum+=$x;
}
echo $sum;
echo $count;
add your elements into an array and then use array_sum to sum the array elements , then divide the sum by the count of your array
$arr = [];
for ($x = 3; $x < 100; $x+=3) {
// echo $x.", \n";
$arr[] = $x;
}
print_r(array_sum($arr) / count($arr));
// Output : 51
$i=0;
$tempx=0;
for ($x = 3; $x < 100; $x+=3) {
//total sum
$tempx = $tempx + $x;
//count of how many times the loop ran in this case 33 times
$i++;
}
//first $i was 0 so we add 1
$i=$i + 1;
//getting the average
$average=$tempx / $i;
echo $average;
//output
For the last answer i think we should not do:
//first $i was 0 so we add 1 $i=$i + 1;
Regards

PHP Calculation, break point, and reset value in foreach loop

How do you calculate (sum) + a value in foreach loop?
I am working on a cricket application where i have to count the loop for each 6 times and then count specific value and then echo the total.
I have a code not exact but something like this.
And there are two values:
Balls $balls['1']; array like 1,2,3,4,5 and up to 300-1000 balls
Runs $balls['6']; array like 2,3,1,5 random numbers could be any;
Values comes from mysql table columns balls and runs
foreach( $balls as $ball ){
$countball++;
// here is what i need to know how do i calculate the values of $ball + $ball?
// so i can echo it inside the below if condition?
$runs = $ball['runs'] + $ball['runs']; // not working
if($countball == 6){
echo $runs;
}
$runs+= $ball; // reset the ball counting to continue addition from loop?
// and reset the
}// end foreach
however something like this works fine for the first $countball == 6. but after that it does not show the exact value
You forget to reset the $countball.
You may change the if part as :
if($countball == 6)
{
echo $runs;
$countball = 0;
}
Maybe this is what you need:
$runs = 0;
foreach( $balls as $ball ){
$runs += $ball['runs'];
}
echo $runs;
With help of #Barmar from above i got the desired output as followings
$runs = 0;
$countball=0;
foreach( $balls as $ball ){
$countball++;
$runs += $ball['runs'];
if($countball == 6){
// reset runs from current loop runs for next, if i reset $runs = 0
// for some reason it does not (SUM) + this loops $ball['runs'] with last 5;
$runs = $ball['runs'];
$countball=0;
}// end if $countball == 6
}// end foreach
echo $runs;

Using for loop instead of if statement?

I am trying to familarise myself with for loop as I only understand the basics.
I am trying to simplify the code below
$round1 = $max / 2;
$round2 = $round1 + ($max / 2 / 2);
$round3 = $round2 + ($max / 2 / 2 / 2);
$round4 = $round3 + ($max / 2 / 2 / 2 / 2);
$round5 ...
With this:-
$round = array($max/2);
for ($i=1;$i<$max;$i++) {
$round[] = $round[$i -1] + $max/pow(2, $i + 1);
}
And now for the next code:-
if($matchno <= $round[0]) {
$scores_round1.= '['.$score1.', '.$score2.'],';
}
if($matchno > $round[0] AND $matchno <= $round[1]) {
$scores_round2.= '['.$score1.', '.$score2.'],';
}
if($matchno > $round[1] AND $matchno <= $round[2]) {
$scores_round3.= '['.$score1.', '.$score2.'],';
}
if($matchno > $round[2] AND $matchno <= $round[3]) {
$scores_round4.= '['.$score1.', '.$score2.'],';
}
Can the above be used in a for loop to avoid using if() ?
Thanks for help
You can check for round1 and for the rest:
for ($i=1;$i<$max;$i++) {
if($matchno>$round[$i] AND $matchno <= $round[$i+1])
${'scores_round'.$i}.='['.$score1.', '.$score2.'],';
}
for($i=0;$i< count($round); $i++){
if($match < $round[$i]){
${"scores_round".$i}.= '['.$score1.', '.$score2.'],';
break;
}
}
By watching the if statements, we notice some things:
First of all, there is no *else if* statement. That means that all if statement checks must be executed.
Additionally, there is a check whether the $matchno is less than $round[0], without any check for greater than in this if statement (the first one).
Another point is that $scores_roundX starts with X=1 and not 0.
Obviously, you will have to use one if inside the loop.
So, we are going to form loop code making some small tricks:
for($i = -1; $i < count($round)-1 ; ++$i){
if(($i = -1 OR $matchno > $round[$i]) AND ($matchno <= $round[$i+1])){
${"scores_round".$i+2} .= '['.$score1.', '.$score2.'],';
}
}
We will initialize THE $i with -1, to use it for the first statement execution.
We will put as for statement the $ to be less than the count of the
array minus 1 (because we index using $i+1 in our if statement,
inside the loop).
We will perform greater than check only if the $i is not -1, and this
will happen on the second check (second if in initial code). Here, we also use
the partial evaluation feature of the language, and that means that in the OR sub-statement,
if the first part comes as true, the second one is not ecaluated.
We will make $i+2 at the $scores_round forming, because we start from
-1 on our for loop.

PHP: Next Available Value in an Array, starting with a non-indexed value

I've been stumped on this PHP issue for about a day now. Basically, we have an array of hours formatted in 24-hour format, and an arbitrary value ($hour) (also a 24-hour). The problem is, we need to take $hour, and get the next available value in the array, starting with the value that immediately proceeds $hour.
The array might look something like:
$goodHours = array('8,9,10,11,12,19,20,21).
Then the hour value might be:
$hour = 14;
So, we need some way to know that 19 is the next best time. Additionally, we might also need to get the second, third, or fourth (etc) available value.
The issue seems to be that because 14 isn't a value in the array, there is not index to reference that would let us increment to the next value.
To make things simpler, I've taken $goodHours and repeated the values several times just so I don't have to deal with going back to the start (maybe not the best way to do it, but a quick fix).
I have a feeling this is something simple I'm missing, but I would be so appreciative if anyone could shed some light.
Erik
You could use a for loop to iterate over the array, until you find the first that is greater than the one you're searching :
$goodHours = array(8,9,10,11,12,19,20,21);
$hour = 14;
$length = count($goodHours);
for ($i = 0 ; $i < $length ; $i++) {
if ($goodHours[$i] >= $hour) {
echo "$i => {$goodHours[$i]}";
break;
}
}
Would give you :
5 => 19
And, to get the item you were searching for, and some after that one, you could use something like this :
$goodHours = array(8,9,10,11,12,19,20,21);
$hour = 14;
$numToFind = 2;
$firstIndex = -1;
$length = count($goodHours);
for ($i = 0 ; $i < $length ; $i++) {
if ($goodHours[$i] >= $hour) {
$firstIndex = $i;
break;
}
}
if ($firstIndex >= 0) {
$nbDisplayed = 0;
for ($i=$firstIndex ; $i<$length && $nbDisplayed<$numToFind ; $i++, $nbDisplayed++) {
echo "$i => {$goodHours[$i]}<br />";
}
}
Which would give you the following output :
5 => 19
6 => 20
Basically, here, the idea is to :
advance in the array, until you find the first item that is >= to what you are looking for
get out of that first loop, when found
If a matching item was found
loop over the array, until either its end,
or you've found as many items as you were looking for.
You can also use the SPL FilterIterator. Though it's not the fastest solution there is, it has the advantage that you can "prepare" the iterator somewhere/anywhere and then pass it to a function/method that doesn't have to know how the iterator works on the inside, i.e. you could pass a completely different iterator the next time.
class GreaterThanFilterIterator extends FilterIterator {
protected $threshold;
public function __construct($threshold, Iterator $it) {
$this->threshold = $threshold;
parent::__construct($it);
}
public function accept() {
return $this->threshold < parent::current();
}
}
function doSomething($it) {
// no knowledge of the FilterIterator here
foreach($it as $v) {
echo $v, "\n";
}
}
$goodHours = array(8,9,10,11,12,19,20,21);
$it = new GreaterThanFilterIterator(14, new ArrayIterator($goodHours));
doSomething($it);
prints
19
20
21
As $goodHours is already sorted, that's something easy:
$next = 0;
foreach($goodHours as $test)
if($test > $hour && $next = $test)
break;
After that four-liner (that can be written in a smaller number of lines naturally), $next is either 0 if $hour could not be matched in $goodHours or it contains the value that immediately proceeds $hour. That is what you asked for.
This only works when $goodHours is sorted, in case it's not, you can sort it by using the asort() function.
Try this function:
function nextValueGreaterThan($haystack, $needle, $n=1) {
sort($haystack);
foreach ($haystack as $val) {
if ($val >= $needle) {
$n--;
if ($n <= 0) {
return $val;
}
}
}
}
$goodHours = array(8,9,10,11,12,19,20,21);
echo nextValueGreaterThan($goodHours, 14); // 19
echo nextValueGreaterThan($goodHours, 14, 3); // 21
Here's an answer similar to the rest of these, including an optional "offset" parameter, that gets your n'th item past the de-facto first one.
class GoodHours {
private $hours = array(8,9,10,11,12,19,20,21);
public function getGoodHour($hour, $offset = 0) {
$length = count($this->hours);
for ($i = 0 ; $i < $length && $this->hours[$i] < $hour ; $i++)
; // do nothing
return $this->hours[($i + $offset) % $length];
}
}
// some test values
$good = new GoodHours();
$x = $good->getGoodHour(5); // 8
$x = $good->getGoodHour(5,1); // 9
$x = $good->getGoodHour(5,2); // 10
$x = $good->getGoodHour(10); // 10
$x = $good->getGoodHour(10,1); // 11
$x = $good->getGoodHour(10,2); // 12
$x = $good->getGoodHour(21); // 21
$x = $good->getGoodHour(21,1); // 8
$x = $good->getGoodHour(21,2); // 9
$x = $good->getGoodHour(21); // 8
$x = $good->getGoodHour(22,1); // 9
$x = $good->getGoodHour(22,2); // 10

Categories