Decoding function to better understand - php
I am revisiting PHP and want to relearn where i lack and i found one problem, i am unable to understand the following code, where as it should output 6 according to the quiz, i got it from but i broke it down to simple pieces and commented out to better understand, according to me the value of $sum should be 4, but what i am doing wrong, maybe my breakdown is wrong?
$numbers = array(1,2,3,4);
$total = count($numbers);
//$total = 4
$sum = 0;
$output = "";
$i = 0;
foreach($numbers as $number) {
$i = $i + 1;
//0+1 = 1
//0+2 = 2
//0+3 = 3
//0+4 = 4
if ($i < $total) {
$sum = $sum + $number;
//1st time loop = 0 < 4 false
//2nd time loop = 0 < 1 false
//3rd time loop = 0 < 2 false
//5th time loop = 0 < 3 false
//6th time loop = 4 = 4 true
//$sum + $number
//0 + 4
//4
}
}
echo $sum;
This is very basic question and might get down vote but it is also a strong backbone for people who want to become PHP developer.
You don't understand the last part in the loop. It actually goes like this now:
if($i < $total) {
$sum = $sum + $number;
//1st time loop: $sum is 0. $sum + 1 = 1. $sum is now 1.
//2nd time loop: $sum is 1. $sum + 2 = 3. $sum is now 3.
//3rd time loop: $sum is 3. $sum + 3 = 6. $sum is now 6.
//4th time loop: it doesn't get here. $i (4) < $total (4)
//This is false, so it doesn't execute this block.
}
echo $sum; // Output: 6
I altered your script a little so that it will print out what it's doing as it goes. I find it useful to do this kind of thing if I'm having a hard time thinking through a problem.
$numbers = array(1,2,3,4);
$total = count($numbers);
$sum = 0;
$i = 0;
$j = 0;
foreach($numbers as $number) {
$i = $i + 1;
echo "Iteration $j: \$i +1 is $i, \$sum is $sum, \$number is $number";
if ($i < $total) {
$sum = $sum + $number;
echo ", \$i is less than \$total ($total), so \$sum + \$number is: $sum";
} else {
echo ", \$i is not less than \$total ($total), so \$sum will not be increased.";
}
echo '<br>'; // or a new line if it's CLI
$j++;
}
echo $sum;
Lets Explain
Your initial value of $i is 0 but when you start looping you increment it by 1, so the start value of $i is 1.
When checking the condition you did't use equal sign to check for the last value whether you start value is 1. So its clear that your loop must be run for 1 less of total.
$i = 0;
foreach($numbers as $number) {
$i += 1;
if ($i < $total)
$sum += $number;
}
echo $sum;
Analysis
Step: 1 / 4
The value of $number is: 1 And The value of $i is: 1
Step: 2 / 4
The value of $number is: 2 And The value of $i is: 2
Step: 3 / 4
The value of $number is: 3 And The value of $i is: 3
When the loop again go for a check the value of $i increased by 1 and at 4. So trying to match the condition if ($i < $total), where the value of $i and $total is equal, so it will return false. So the loop only run for 3 time.
Result
6
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
PHP: for loop $i value turns zero if the number is greater
I want to turn the $i variable value to start counting from 1 if the given value is greater than 10: here is what i am trying to achieve <?php $givenValue = 15; //number of x value for ($i = 1; $i < $givenValue; $i++) { if ($givenValue > 10){ $i = 1; } echo $i."<br>"; } ?> This is how i want my result to look like output: 1 output: 2 output: 3 output: 4 output: 5 output: 6 output: 7 output: 8 output: 9 output: 10 output: 1 output: 2 output: 3 output: 4 output: 5 in for loop body Any help is welcome
You can use modulo calculation to get the result you want. I also changed your if from $givenvalue to $i as $givenvalue will "always" be 10+. $givenValue = 15; //number of x value for ($i = 1; $i <= $givenValue; $i++) { if ($i > 10){ Echo $i%10 . "\n"; }else{ echo $i . "\n"; } } https://3v4l.org/5afc5 Another option, if that is possible for you, is to start at zero and only use modulo calculation and add one to it to get the same result. This also means I need to stop the loop at <$givenvalue as your original code shows. $givenValue = 15; //number of x value for ($i = 0; $i < $givenValue; $i++) { Echo $i%10+1 . "\n"; } https://3v4l.org/r0sgA A method that uses less looping is to add 10 to the loop on each iteration and create the values using range(). Then add them to the array with array_merge, and output with implode. $givenValue = 47; //number of x value $breakpoint = 10; $arr=[]; For($i = $breakpoint; $i< $givenValue;){ // Add new values from 1-$breakpoint in array $arr = array_merge($arr, range(1,$breakpoint)); $i +=$breakpoint; } // Loop will exit before all values been collected // Add the rest of the values $arr = array_merge($arr, range(1,$givenValue-($i-10))); // Echo the values in array Echo implode("\n", $arr); https://3v4l.org/jGsO4
Your code can be written like this: <?php $givenValue = 15; //number of x value for ($i = 1; $i <= $givenValue; $i++) { if ($i > 10) { $i = 1; $givenValue-=10; } echo "output: $i\n"; } ?> http://sandbox.onlinephpfunctions.com/code/ed34d8dcd12a9a5a866b73338ad1209f55298519
You are resenting the counter, I would expect the behaviour you have. To do what you want add another counter to the mix $j=1; $givenValue = 15; //number of x value for ($i = 1; $i <= $givenValue; $i++) { if ($j > 10){ $j = 1; } echo $j."\n"; ++$j; } You also had several missing ; Output: 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 If you want to end on 5 you have to do 16 as the $givenValue or change it to <= less than or equal See it here live See what I have now, the $i variable counts to the $givenValue then the $j variable counts along side it, but with a range of 1-10 ( resets to 1 after 10 )
array within indexed numbers
I tried to test a new thing and just saw an unusual output I am unable to get what exactly is happening within the loop can anyone explain me what happens if we take an array and assign that array to a variable we run a for loop and we provide $array and index of $array with the inititlizer for forloop something like this $array[$array[$i]] so I mean I am confused to totally explain but can you review the code and let me know what exactly is happening $array = array(1, 2, 3, 5, 8, 13, 21, 34, 55); $sum = 0; for($i = 0; $i < 5; $i++) { $sum += $array[$array[$i]]; } echo $sum ; The output 78 as it added the value but if i remove $sum+= and write down like this echo $array[$array[$i]] . "<br />"; so now what here is I will be getting output like this 2 3 5 13 55 I am unable to get what exactly hapend within this loop
You are using the value of the array to access the key. $array = array(1, 2, 3, 5, 8, 13, 21, 34, 55); $sum = 0; for($i = 0; $i < 5; $i++) { $sum += $array[$array[$i]] . "<br />"; } echo $sum ; Loop 1: $i = 0; $sum += $array[$array[0]]; $sum += $array[1]; $sum += 2; Loop 2: $i = 1; $sum += $array[$array[1]]; $sum += $array[2]; $sum += 3; Loop 3: $i = 2; $sum += $array[$array[2]]; $sum += $array[3]; $sum += 5; Loop 4: $i = 3; $sum += $array[$array[3]]; $sum += $array[5]; $sum += 13; Loop 5: $i = 4; $sum += $array[$array[4]]; $sum += $array[8]; $sum += 55; So... $sum = 2 + 3 + 5 + 13 + 55 = 80
For $i = 0 what is $array[$i] -> $array[0] -> 1. what is $array[$array[$i]] -> $array[1] -> 2. And so on.
First iteration ($i = 0) $array[$i] = $array[0] = 1 and $array[1] = 2 Second iteration ($i = 1) $array[$i] = $array[1] = 2 and $array[2] = 3 Third iteration ($i = 2) $array[$i] = $array[2] = 3 and $array[3] = 5 Fourth iteration ($i = 3) $array[$i] = $array[3] = 5 and $array[5] = 13 Fifth iteration ($i = 4) $array[$i] = $array[4] = 8 and $array[8] = 55
When $i = 0 $array[$array[$i]] becomes $array[$array[0]] which is $array[1] since $array[0] = 1. So $array[1] evaluates to 2. Keep thinking the same way. For example, for $i = 4 $array[$array[$i]] becomes $array[$array[4]] which is $array[8] since $array[4] = 8. So $array[8] evaluates to 55. Think step by step.
Simple PHP program requires less time to execute
i had applied for a job recently and the requirement was to complete a test and then interview 2 questions were given for test which was very simple and i did it successfully but still i was told that i have failed the test because the script took more than 18 seconds to complete execution. here is the program i dont understand what else i could do to make it fast. although i have failed the test but still wants to know else i could do? Program language is PHP and i had to do it using command line input here is the question: K Difference Given N numbers , [N<=10^5] we need to count the total pairs of numbers that have a difference of K. [K>0 and K<1e9] Input Format: 1st line contains N & K (integers). 2nd line contains N numbers of the set. All the N numbers are assured to be distinct. Output Format: One integer saying the no of pairs of numbers that have a diff K. Sample Input #00: 5 2 1 5 3 4 2 Sample Output #00:3 Sample Input #01: 10 1 363374326 364147530 61825163 1073065718 1281246024 1399469912 428047635 491595254 879792181 1069262793 Sample Output #01: 0 Note: Java/C# code should be in a class named "Solution" Read input from STDIN and write output to STDOUT. and this is the solution $fr = fopen("php://stdin", "r"); $fw = fopen("php://stdout", "w"); fscanf($fr, "%d", $total_nums); fscanf($fr, "%d", $diff); $ary_nums = array(); for ($i = 0; $i < $total_nums; $i++) { fscanf($fr, "%d", $ary_nums[$i]); } $count = 0; sort($ary_nums); for ($i = $total_nums - 1; $i > 0; $i--) { for ($j = $i - 1; $j >= 0; $j--) { if ($ary_nums[$i] - $ary_nums[$j] == $diff) { $count++; $j = 0; } } } fprintf($fw, "%d", $count);
Your algorithm's runtime is O(N^2) that is approximately 10^5 * 10^5 = 10^10. With some basic observation it can be reduced to O(NlgN) which is approximately 10^5*16 = 1.6*10^6 only. Algorithm: Sort the array ary_nums. for every i'th integer of the array, make a binary search to find if ary_nums[i]-K, is present in the array or not. If present increase result, skip i'th integer otherwise. sort($ary_nums); for ($i = $total_nums - 1; $i > 0; $i--) { $hi = $i-1; $low = 0; while($hi>=$low){ $mid = ($hi+$low)/2; if($ary_nums[$mid]==$ary_nums[$i]-$diff){ $count++; break; } if($ary_nums[$mid]<$ary_nums[$i]-$diff){ $low = $mid+1; } else{ $hi = $mid-1; } } } }
I got the same question for my technical interview. I wonder if we are interviewing for the same company. :) Anyway, here is my answer I came up with (after the interview): // Insert code to get the input here $count = 0; sort ($arr); for ($i = 0, $max = $N - 1; $i < $max; $i++) { $lower_limit = $i + 1; $upper_limit = $max; while ($lower_limit <= $upper_limit) { $midpoint = ceil (($lower_limit + $upper_limit) / 2); $diff = $arr[$midpoint] - $arr[$i]; if ($diff == $K) { // Found it. Increment the count and break the inner loop. $count++; $lower_limit = $upper_limit + 1; } elseif ($diff < $K) { // Search to the right of midpoint $lower_limit = $midpoint + 1; } else { // Search to the left of midpoint $upper_limit = $midpoint - 1; } } } #Fallen: Your code failed for the following inputs: Enter the numbers N and K: 10 3 Enter numbers for the set: 1 2 3 4 5 6 7 8 9 10 Result: 6 I think it has to do with your calculation of $mid (not accounting for odd number)
how to find the sum of all the multiples of 3 or 5 below 1000 in php, issue?
i have an small issue with the way this problem is resolved. some would say: println((0 /: ((0 until 1000).filter(x => x % 3 == 0 || x % 5 == 0))) (_+_)) is the solution witch adds to 233168 my way was to do: $maxnumber = 1000; for ($i = 3; $i < $maxnumber; $i += 3) { $t += $i; echo $i.','; } echo '<br>'; for ($j = 5; $j < $maxnumber; $j += 5) { $d += $j; echo $j.','; } echo '<br>'; echo $t; echo '<br>'; echo $d; echo '<br>'; echo $t+$d; this will give me : 3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60,63,66,69,72,75,78,81,84,87,90,93,96,99,102,105,108,111,114,117,120,123,126,129,132,135,138,141,144,147,150,153,156,159,162,165,168,171,174,177,180,183,186,189,192,195,198,201,204,207,210,213,216,219,222,225,228,231,234,237,240,243,246,249,252,255,258,261,264,267,270,273,276,279,282,285,288,291,294,297,300,303,306,309,312,315,318,321,324,327,330,333,336,339,342,345,348,351,354,357,360,363,366,369,372,375,378,381,384,387,390,393,396,399,402,405,408,411,414,417,420,423,426,429,432,435,438,441,444,447,450,453,456,459,462,465,468,471,474,477,480,483,486,489,492,495,498,501,504,507,510,513,516,519,522,525,528,531,534,537,540,543,546,549,552,555,558,561,564,567,570,573,576,579,582,585,588,591,594,597,600,603,606,609,612,615,618,621,624,627,630,633,636,639,642,645,648,651,654,657,660,663,666,669,672,675,678,681,684,687,690,693,696,699,702,705,708,711,714,717,720,723,726,729,732,735,738,741,744,747,750,753,756,759,762,765,768,771,774,777,780,783,786,789,792,795,798,801,804,807,810,813,816,819,822,825,828,831,834,837,840,843,846,849,852,855,858,861,864,867,870,873,876,879,882,885,888,891,894,897,900,903,906,909,912,915,918,921,924,927,930,933,936,939,942,945,948,951,954,957,960,963,966,969,972,975,978,981,984,987,990,993,996,999 5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140,145,150,155,160,165,170,175,180,185,190,195,200,205,210,215,220,225,230,235,240,245,250,255,260,265,270,275,280,285,290,295,300,305,310,315,320,325,330,335,340,345,350,355,360,365,370,375,380,385,390,395,400,405,410,415,420,425,430,435,440,445,450,455,460,465,470,475,480,485,490,495,500,505,510,515,520,525,530,535,540,545,550,555,560,565,570,575,580,585,590,595,600,605,610,615,620,625,630,635,640,645,650,655,660,665,670,675,680,685,690,695,700,705,710,715,720,725,730,735,740,745,750,755,760,765,770,775,780,785,790,795,800,805,810,815,820,825,830,835,840,845,850,855,860,865,870,875,880,885,890,895,900,905,910,915,920,925,930,935,940,945,950,955,960,965,970,975,980,985,990,995 $t - 166833 $d - 99500 and total: 266333 why am i wrong?
Some numbers are multiples of both 3 and 5. (Your algorithm adds these numbers to the total twice.)
Because 6 * 5 == 30 and 10 * 3 == 30, you're adding the some numbers up twice. $sum = 0; $i = 0; foreach(range(0, 999) as $i) { if($i % 3 == 0 || $i % 5 == 0) $sum += $i; }
Because you double-count numbers that are multiple of both 3 and 5, i.e. multiples of 15. You can account for this naively by subtracting all multiples of 15. for ($j = 15; $j < $maxnumber; $j += 15) { $e += $j; echo $j.','; } $total = $total - $d;
In your case, if it is 15, you will add the number twice. Try this: $t = 0; $d = 0; for ($i = 0; $i <= $maxnumber; $i++){ if ($i % 3 == 0) $t+= $i; else if ($i % 5 == 0) $d += $i; } echo $t.'<br>'.$d;
I think that in your code, if a number is a multiple of 3 and 5, it is added twice. Take 15 for example. It's in your list of multiples of 3 and in the list of multiples of 5. Is this the behaviour you want?
One of the best approach to this solution (to achieve optimum time complexity), run an Arithmetic Progression series and find the number of terms in all series by using AP formula: T=a+(n-1)d, then find sum by : S=n/2[2*a+(n-1)d] where : a=first term ,n=no. of term , d=common deference, T=nth term The code solution below has been implemented to suit the question above - so the values 3 and 5 are hard-coded. However, the function can modified such that values are passed in as variable parameters. function solution($number){ $val1 = 3; $val2 = 5; $common_term = $val1 * $val2; $sum_of_terms1 = calculateSumofMulitples($val1,$number); $sum_of_terms2 = calculateSumofMulitples($val2,$number); $sum_of_cterms = calculateSumofMulitples($common_term,$number); $final_result = $sum_of_terms1 + $sum_of_terms2 - $sum_of_cterms; return $final_result; } function calculateSumofMulitples($val, $number) { //first, we begin by running an aithmetic prograssion for $val up to $number say N to get the no of terms [using T=a +(n-1)d] $no_of_terms = (int) ($number / $val); if($number % $val == 0) $no_of_terms = (int) ( ($number-1)/$val ); //since we are computing for a no of terms below N and not up to/exactly/up to N. if N divides val with no remainder, use no of terms = (N-1)/val //second, we compute the sum of terms [using Sn = n/2[2a + (n-1)d] $sum_of_terms = ($no_of_terms * 0.5) * ( (2*$val) + ($no_of_terms - 1) * $val ); // sum of multiples return $sum_of_terms; }
You can run a single loop checking whether the number is multiple of 3 OR 5: for ($i = 0; $i < $maxnumber; $i++) { if($i%3 || $i%5){ $t += $i; echo $i.',';} }
I think the original code is not including numbers which are multiples of both 3 and 5 in the total: if the test for multiple of 3 matches, it takes that and goes on. If you total the multiples of 15 up to 1000, you get 33165, which is exactly the difference between your total, 266333, and the original total, 233168.
Here's my solution to the question: <?php $sum = 0; $arr = []; for($i = 1; $i < 1000; $i++){ if((int)$i % 3 === 0 || (int)$i % 5 === 0) { $sum += $i; array_push($arr,$i); } } echo $sum; echo '<br>'; print_r($arr);//Displays the values meeting the criteria as an array of values