PHP: increment a number by 5 each time - php

I'm trying to reproduce the following as a one-liner.
if($l < 10) $next = 5; return;
if($l < 20) $next = 10; return;
if($l < 30) $next = 15; return;
if($l < 40) $next = 20; return;
if($l < 50) $next = 25; return;
if($l < 60) $next = 30; return;
if($l < 70) $next = 35; return;
if($l < 80) $next = 40; return;
if($l < 90) $next = 45; return;
if($l < 100) $next = 50; return;
(not syntactically correct but you get the idea)
So that if the number is less than 10, $next is 5, and if the number is less than 20 then it's 10.
$next = ((round($l, -1)-5)); is as close as I can get to it but that gives
5
15
25
35
45
55
65
75
85
not the desired 5, 10, 15, 20 .. etc
What is the correct way to write this?

add 10 to your number, then divide the result by 10 and round it down to the nearest (floor) integer, you will then have the number by which to multiply 5, which will yield your result... so...
let's say your number is 47.
47 + 10 = 57
57 / 10 = 5.7
floor 5.7 = 5
5x5 = 25
return floor(($i + 10)/10) * 5

(($l + 10) / 10) * 5 will do the trick

DIVDIDE through ten (and round that to int), then multiply that with 5 ... 100/10=10 => 10*5=50

This might do:
$i=10;
while($l < $i){
$next = $i / 2;
$i+=10;
}

If I understand your question correctly, it's not harder than;
$next = floor($l/10)*5+5;

Related

How to calculate total cost based on price ranges of items

I need to calculate total cost of items, based on ranges:
if ($itemCount <11)
{
$cost_for_range = 1;
}
if ($itemCount <26 && $itemCount >=11)
{
$cost_for_range = 0.75;
}
if ($itemCount <50 && $itemCount >=26)
{
$cost_for_range = 0.55;
}
Thing is - I need to count final cost taking earlier levels into consideration - eg if the cart has 30 items, the price would be:
first 10 at $1 = $10
another 15 at $0.75 = $11.25
another 5 at $0.55 = $2.75
so total would be $24.
How to calculate this in php?
Try this :
$itemCount = 25;
$total = 0;
for ( $i = 0 ; $i < $itemCount ; $i++ ) {
if ( $i < 10 ) {
$total += 1;
} else if ( $i < 25 ) {
$total += 0.75;
} else if ( $i < 50 ) {
$total += 0.55;
} else {
$total += 0; // price if more than 50
}
}
Having some fun using min and max to do the various ranges...
function calculateCost ( int $count, float $cost ) {
$total = min(10, $count) * $cost;
$total += (min(15, max(0, $count - 10)) * ($cost * 0.75));
$total += (max(0, $count - 25) * ($cost * 0.55));
return $total;
}
the second calculation uses max(0, $count - 10), so this takes the first 10 off, but ensures it doesn't go negative. Then it uses the min(15, max(0, $count - 10)) to take the lowest of 15 or the number left (so with 30, this will be 15).
The last one is just the max of the count - 25 or 0, so for 30, this is 5.
Use it with...
echo calculateCOst( 30, 1 );
gives 24
For a universal solution, it is good to define the discounts in an array. This solution is then ready for extensions and changes.
$rebate = [10 => 1.0, 15 => 0.75, PHP_INT_MAX => 0.55];
The number and the discount array are transferred to the function that calculates the cost factor. The calculation itself is realized with a simple forech loop with termination condition.
function calcCostFactor(int $count, array $rebate){
$factor = 0.0;
foreach($rebate as $number => $val){
$factor += min($count,$number) * $val;
$count -= $number;
if($count <= 0) break;
}
return $factor;
}
example:
$factor = calcCostFactor(30, $rebate);
Try it self.

PHP Create a while-loop that subtracts?

I got this Exercise :
Create a while-loop that subtracts 5.23 from the number 526 until the number is between (not equal to) 41 and 51. Answer with the final result as a float, rounded to 2 decimals.
What I doing wrong ?
$number = 1;
$sum = 526;
while ($number > 41 && $number < 51)
{
$sum-=5.23;
$number++;
}
Your loop never actually runs as 1 is never > 41 && < 51
$sum = 526;
while (1)
{
$sum -= 5.23;
if ( $sum > 41 && $sum < 51 ) { break; }
}
$ANSWER = sprintf('%2.2f', $sum);
echo $ANSWER;

PHP-Relooping array associative backwards

I have a created a grid like this (some gaps has an obstacle, but it is not important for the question):
private function newGrid()
{
$grid = array();
for ($i = 0; $i < 10; $i++) {
for ($j = 0 ; $j < 10; $j++) {
$grid[$i][$j] = ['obstacle' => rand(0,1)];
}
}
return $grid;
}
So, the initial location is an array:
$loc = array('x' => 1, 'y' => 3);
For example, if i'm moving to x direction, I want wrapping from one edge of the grid to another(like an sphere). (Forward and backward)
When i'm going forward I'm using the modulus like this:
$loc['x'] = ($loc['x'] + 1) % 10 ;
But if I want to do the same, but going backwards, which is the better way to do that? when x gets to 0, go to position x = 9
Any suggestion?
For going backwards you can do:
$loc['x'] = ($loc['x'] + 9) % 10 ;
If you have dynamic "direction" variable which can take values 1 (forward) and -1 (backwards), then:
$loc['x'] = ($loc['x'] + 10 + $direction) % 10 ;
Maybe this would be a practical function:
function move($loc, $deltaX, $deltaY) {
$loc['x'] = ($loc['x'] + 10 + $deltaX) % 10;
$loc['y'] = ($loc['y'] + 10 + $deltaY) % 10;
return $loc;
}

round to nearest multiple of 5 in a range in php

I have this if statement:
if($_GET["angle_1"] > 39) {
$markers["###ANGLE###"] = "45";
} elseif($_GET["angle_1"] > 29 && $_GET["angle_1"] < 40) {
$markers["###ANGLE###"] = "35";
} elseif($_GET["angle_1"] < 30) {
$markers["###ANGLE###"] = "25";
} else {
$markers["###ANGLE###"] = "45";
}
Is there a better / simpler way to do this check, f.x. with round that will round the integer to the nearest 5, i.e. 28 -> 25 or 34 -> 35 etc. and in that, if the integer is less than 25, it will always be 25 and if the integer is higher than 45, it will always be 45 and again if the integer is between 30 and 40 it will always be 35.
That returned value will be used to display an image.
EDIT:
I have 3 images: image_25, image_35 and image_45, therefore the need to round.
Let say $x has the number:
$x = 39;
If you want the closest multiple of 5 (39 --> 40):
$x = round($x / 5) * 5;
If you want to round up (36 --> 40):
$x = ceil($x / 5) * 5;
If you want to round down (39 --> 35):
$x = floor($x / 5) * 5;
After defining $x, you can use the following to make sure its in the 25-45 range:
$x = ($x > 45) ? 45 : ($x < 25) ? 25 : $x;
Give this a try:
$var = 5 * round($n / 5);
Taken from here

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

Categories