calculation for different value ranges - php

I need help with the next problem...
I have a list of values... prices in my case.
Im converting a csv file with prices. all is very good, but i need a solution to calculate a discount for a range of price.
Ex:
1234 , 230
2345, 500
5432 , 800
"modified"
i need to apply a discount of
3% off for values range 100-250
10% off for values range 250-500
25% off for values range 500-1000
so, i have the column with values.
$values[2]
$formula = round($values * 0.97, 0); // this is only geting 3% for all values from column.
But i need help to get the correct disocunt for a range all ranges.
Thanks

if ($values[2] >= 100 && $values[2] <= 250) {
$discount = 0.97;
}
else if ($values[2] > 250 && $values[2] <= 500) {
$discount = 0.9;
}
else if ($values[2] > 500 && $values[2] <= 1000) {
$discount = .75;
}
Am I missing something here?

Related

PHP Calculate fee by price range

Is anyone who can help me to create PHP and mysql Code. Here is the condition.
If price range is 1 to 20 USD, it will be show 2 USD.
If price range is 21 to 50 USD, it will be show 5 USD.
If price range is 51 to 100 USD, it will be show 7 USD.
how to do it with PHP or WordPress php coding.
I don't get the MySQL part here did you want to do this on the database level? or are you looking for both? anyway, in PHP it should be like this
$price = 5;
if($price >= 1 && $price <= 20){
$price = 2;
}else if($price > 20 && $price <= 50){
$price = 5;
}else if($price > 50 && $price <= 100){
$price = 7;
}
Note: you should be careful with the ranges 20.1 is greater than 20 but it is less than 21
I hope it's helpful
If you're using PHP 8, this would be elegantly done with match:
$fee = match(true) {
$price <= 20 => 2,
$price <= 50 => 5,
$price <= 100 => 7,
default => 0 // free shipping!
};
Since the evaluation ends when a "match arm" matches, we don't need to define the lower range -- as long as our ranges are defined in ascending order. I haven't used $price >= 1 && $price <= 20 => 2 for the first condition, assuming that $0.50 still costs something.
Since we're evaluating for the truth of expressions (true|false), a simple match($fee) wouldn't work. We need match(true) instead, where, when an expression evaluates as true, the corresponding value will be returned. Note that match must be exhaustive, ie. it must have a default condition if none of the conditions match (or you get an error).
On older PHP versions, the more long-winded switch can be used:
switch(true) {
case ($price >= 1 && $price <= 20):
$fee = 2;
break;
case $price <= 50:
$fee = 5;
break;
case $price <= 100:
$fee = 7;
break;
default:
$fee = 0;
break;
};
While switch doesn't require a default statement, it's a good idea to have a default value for transactions that exceed your ranges. Being nice, I give free shipping for orders > 100.
You can also of course use a series of if/elseif statements, but they become quite clunky if you have more than a small handful of conditions to check. match and switch exist to make cases like this more readable and easier to maintain.
Per #AhmedHassan's notes, your logic has a gap between 20/21, and 50/51. The next step from "less than or equal to 20" has to be "more than 20, less than or equal with 50". Or, if $20 flat already incurs the higher fee, then you should use >= 20 and < 50 for your price range boundaries.

How to determine every 100 item in a while loop php?

I'm currently learning PHP, and I'm struggling with this:
"For every 100 ordered products in a category, 2% will be deducted:"
This is my code:
$gesA = 309; // (The amount of product)
$gesN = 1011.08; // (The full price of product)
$i = 1;
while($i)
{
if($gesA % 100 == 0)
{
echo $gesN;
echo "<br>";
$gesN = $gesN / 0.2;
}
$i++;
$gesN++;
}
echo $gesN;
Yet, I can't figure it out. Could someone help me?
First you find how many times it is that there are 100 ordered products, which can be calculated by divide the number of products by 100.
$no = $getA / 100;
But that can get you a floating number so you remove the decimal part with floor()
$no = floor($getA / 100);
Then the percentage will be 2% times the integer number.
$deductPercentage = 2 * $no;
And the final product price will be the remaining of the deducted price
$deductedPrice = $gesN * $deductPercentage / 100;
$finalPrice = $gesN - $deductedPrice;

PHP - Packing widgets into the fewest number of boxes, plus minimum order quantity

The problem is this:
A company supplies widgets in a set of pack sizes:
250
500
1000
2000
5000
Customers can order any number of widgets, but the following rules apply:
Only whole packs can be sent and …
No more widgets than necessary should be sent and …
The fewest packs possible should be sent
Some examples showing the number of widgets ordered and the required pack quantities and sizes to correctly fulfill the order:
1 (1 x 250)
251 (1 x 500)
501 (1 x 500 and 1 x 250)
12001 (2 x 5000 and 1 x 2000 and 1 x 250)
I’ve looked at some algorithms (greedy coin change, LAFF, etc.) as these seem to provide similar solutions. However, I'm ideally looking for a scalable, object oriented approach to solving this problem.
Here's what I've come up with so far:
<?php
function countWidgets($amount)
{
$packs = array(5000, 2000, 1000, 500,
250);
$packCounter = array(0, 0, 0, 0, 0);
$packsCount = count($packs);
// loop packs
for ($i = 0; $i < $packsCount; $i++)
{
if ($amount >= $packs[$i])
{
$packCounter[$i] = intval($amount /
$packs[$i]);
$amount = $amount -
$packCounter[$i] *
$packs[$i];
}
}
// if remainder
if ($amount > 0) {
// and if smallest pack size populated
if ($packCounter[4] == 1) {
// clear smallest pack size
$packCounter[4] = 0;
// increment next biggest pack size
$packCounter[3] += 1;
} else {
// increment smallest pack size
$packCounter[4] +=1;
}
}
// Print packs
echo ("Pack ->"."\n");
for ($i = 0; $i < $packsCount; $i++)
{
if ($packCounter[$i] != 0)
{
echo ($packs[$i] . " : " .
$packCounter[$i] . "\n");
}
}
}
$amount = 251;
countWidgets($amount);
OK, I agree that this is a bit harder than I assumed yesterday. You basically have two opposing demands:
No more widgets than necessary should be sent.
The fewest packs possible should be sent.
You cannot fulfill both. So if I tried to send 1200 widgets, rule 2 says I should send a pack of 2000, however, rule 1 says I should send 2 packs: one of 1000 and one of 250. Which rule should prevail?
I chose that rule 1 should prevail in the solution below. The reason is that no customer wants more widgets than absolutely necessary.
$packSizes = [ 250,
500,
1000,
2000,
5000];
function optimizePacks($packSizes,$number)
{
rsort($packSizes);
$requiredPacks = array_fill_keys($packSizes,0);
foreach ($packSizes as $size) {
$packs = floor($number/$size);
if ($packs > 0) {
$requiredPacks[$size] = $packs;
$number -= $packs*$size;
}
}
if ($number > 0) $requiredPacks[min($packSizes)]++;
return $requiredPacks;
}
$packs = optimizePacks($packSizes,6666);
print_r($packs);
This will work for any array of pack sizes and any number of widgets. The output of this code is:
Array (
[5000] => 1
[2000] => 0
[1000] => 1
[500] => 1
[250] => 1 )
Which is one pack more than rule 2 would demand (one of 5000 and two of 1000). It would, of course, be possible to let rule 2 prevail, but I cannot fulfill both rules.

Looking for a more elegant solution to this loop

I tried asking this earlier, but I don't think I phrased the question correctly so I worked out something that got me the result I was after and now am hoping that it will help someone help me.
Problem: I have 10 items. If you buy 1, it's $10. I will sell you the second one for $9. I will sell you the third item for $8. I will keep taking off money until we get to $5/item because that is the lowest I will sell it for. So, if you buy all 10, it will cost you $65.
This is the pricing model I am trying to achieve, except at a much larger scale. Instead of a handful of items using dollars, I'm talking about up to millions and using fractions of pennies.
This is my current code:
<?php
function getCost($num_items)
{
$min_price = 0.002;
$max_price = 0.007;
$discount_range = 1000000;
$discount_per_additional_item = ($max_price - $min_price) / ($discount_range - 1);
$price_per_unit = MAX($min_price, ($max_price - ($num_items - 1) * $discount_per_additional_item) );
return $price_per_unit;
}
$array = [100, 1000, 10000, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000];
foreach ($array as $value)
{
$sum = 0;
for ($i = 0; $i < $value; ++$i)
$sum += getCost($i);
echo number_format($value) . ' | $' . number_format($sum) . "\n";
}
Which results in:
100 | $1
1,000 | $7
10,000 | $70
100,000 | $675
200,000 | $1,300
300,000 | $1,875
400,000 | $2,400
500,000 | $2,875
600,000 | $3,300
700,000 | $3,675
800,000 | $4,000
900,000 | $4,275
1,000,000 | $4,500
I'm using $array as a sanity check where in the real world, I would simply calculate for the actual number the customer is being charged for.
My question is: Is there a way to accomplish this without using a for loop? Something, perhaps, more elegant?
I made an example online: http://sandbox.onlinephpfunctions.com/code/47e270dbad8cbe16c9ea906ffd2dce098a52fbca
This code will have the same output, and does not have the inner loop:
$min_price = 0.002;
$max_price = 0.007;
$discount_range = 1000000;
$discount_per_additional_item = ($max_price - $min_price)/($discount_range - 1);
$num_progressively_discounted_items =
ceil(($max_price - $min_price) / $discount_per_additional_item);
foreach ($array as $value) {
$num_items_above_min = min($value, $num_progressively_discounted_items);
$num_items_at_min = $value - $num_items_above_min;
$sum = $num_items_at_min * $min_price +
$num_items_above_min * $max_price -
$discount_per_additional_item
* $num_items_above_min * ($num_items_above_min - 1)/2;
echo number_format($value) . ' | $' . number_format($sum) . "\n";
}
This is what it does:
It first checks how many times the unit discount can be subtracted from the original price before hitting the minimum price. If more than the number of items you are buying, then this calculated figure is corrected to that number of items.
The remaining number of items (if any) are also taken note of: these will all have the minimum price.
The sum consists of two parts. The easy part is represented by the number of items that will go for the minimum price, and it is a simple multiplication.
The second part of the sum consists of an always decreasing term, or otherwise put: it is the maximum price for the number of items that don't go for the minimum price, minus the sum of 0+1+2+3+4+5...+n. For that the formula is known: n(n-1)/2.
Like I mentioned in comments, there is something strange in your code: for $i=0 the value returned by getCost($i) is higher than the max price, as the unit discount gets added to it. This can be corrected by starting your inner loop with $i=1. Anyway, this means there is a tiny difference in the result of my proposed code, as it does not have this peculiarity. But as the discount per unit is so tiny, you don't actually notice it in the printed output.
You can do this a little bit more functional style:
function sumOfNaturalSeries($n)
{
return ((1 + $n) / 2) * $n;
}
$minPrice = 0.002;
$maxPrice = 0.007;
$discountRange = 1000000;
$discountStep = ($maxPrice - $minPrice) / $discountRange;
$getPrice = function ($numberOfItems) use (
$minPrice,
$maxPrice,
$discountRange,
$discountStep
) {
if ($numberOfItems <= $discountRange) {
return $maxPrice * $numberOfItems - sumOfNaturalSeries($numberOfItems - 1) * $discountStep;
}
$itemsAboveRange = $numberOfItems - $discountRange;
return $maxPrice * $discountRange - sumOfNaturalSeries($discountRange - 1) * $discountStep + $minPrice * $itemsAboveRange;
};
$array = [100, 1000, 10000, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000];
$sums = array_map($getPrice, $array);
var_dump($sums);
var_dump(array_map('number_format', $sums));
Here is demo.
Take a notice on computational error.

Increment Price by Hundred, Thousand, Ten-Thousand, etc

I'm trying to make a select list of prices in my system. The prices are stored as integers. I'm able to get the lowest price and highest price but I want to display them in a select list. I don't want the select list to increment slowly but by 100 or 10,000 or, 100,000 depending on what my starting number is what where i'm at in my incrementation.
For example, say I have these 2 prices:
500000
12345689
I'm trying to increment them by 100,000 Then when I get to 1,000,000 I want to increment by that. It will look something like this:
500000
600000
700000
800000
900000
1000000
2000000
I'm using a custom function and a bit of formatting to get all my prices and get my start price and end price:
$prices = my_custom_function(); // Pulls All Prices in a random order
if(!empty($prices)){
sort($prices); // Sort Prices Lowest to Highest
$price_low = $prices[0];
$price_high = $prices[count($prices)-1];
$price_start = intval( $price_low[0].str_repeat( '0', strlen( $price_low ) - 1 ) );
$price_end = intval( ( $price_high[0] + 1 ).str_repeat( '0', strlen( $price_high ) -1 ) );
}
Using the same example above, my start price and end price will be:
$price_start = 500000
$price_end = 20000000
Now it's at the loop where I run into trouble incrementing it by the values I want. I'm trying to use a while loop and determine where I am in my incrementer:
<?php $i = $price_start; $x = 0; while($x < 10) : ?>
<option value="<?php echo $i; ?>"><?php echo format_price($i); ?></option>
<?php
if(1000 % $i == 0)
$i+=1000;
else if(10000 % $i == 0)
$i+=10000;
else if(100000 % $i == 0)
$i+=100000;
else if(1000000 % $i == 0)
$i+=1000000;
else
$i+=10000000;
$x++;
endwhile;
?>
I ended up adding in the x variable because I kept running into infinite loop problems but theoretically it should be while($i <= $price_end). Can somebody point me in the right direction on how to get the expected output please? I feel like I'm close but not quite there yet and there's probably a better / faster way to go about it. Any help would be great.
I guess a simplified way of looking at it is:
1 -> +1
10 -> +10
100 -> +100
1000 -> +1000
10000 -> +10000
and so forth.
Get power of 10: log10(1234); // 3.09131
Round down: floor(log10(1234)); // 3
Re-raise as power of 10: pow(10,floor(log10(1234))); // 1000
???
Profit.
If someone needs the full solution here it is:
$price = 100; // Starting Price
$priceEnd = 10000; // Ending Price
while($price <= $priceEnd) {
echo $price . "<br/>";
$increase = pow(10,floor(log10($price)));
$price = $price + $increase;
}

Categories