Postage cost per parcel
A parcel shop prices postage by weight: up to 500 g costs 3.20; from 501 g to 2000 g costs 5.60; heavier parcels cost 5.60 plus 1.10 for every started kilogram above 2000 g, so 2001 g to 3000 g costs 6.70 and 3001 g to 4000 g costs 7.80. Express delivery doubles the price. Write a function postage(int $grams, bool $express): int that returns the price in cents, then read a list of parcels and print the price of each on its own line as euros.cents.
Input
The first line is N, the number of parcels (1 to 200). Each of the next N lines holds a weight in grams (1 to 30000), a space, and yes or no for express.
Output
N lines: the price of each parcel with exactly two decimals, for example 6.70.
Example 1
Input
4 250 no 500 yes 2000 no 2001 no
Output
3.20 6.40 5.60 6.70
250 g is in the first band. 500 g express is 3.20 doubled. 2000 g is still the second band. 2001 g starts a new kilogram above 2000 g, so 5.60 + 1.10.
Example 2
Input
2 3000 yes 3001 no
Output
13.40 7.80
3000 g is one started kilogram over (6.70), doubled for express. 3001 g starts a second kilogram: 5.60 + 2 x 1.10.
Constraints
- 1 <= N <= 200
- 1 <= grams <= 30000
- The second word is exactly
yesorno
Hints
Hint 1 of 3
Work in integer cents (320, 560, 110) inside the function so no rounding can creep in.
Hint 2 of 3
The number of started kilograms above 2000 g is intdiv($grams - 2000 + 999, 1000): adding 999 before dividing rounds up.
Hint 3 of 3
To print cents as money: sprintf('%d.%02d', intdiv($cents, 100), $cents % 100).
Solution
Show a reference solution and explanation
<?php
function postage(int $grams, bool $express): int
{
if ($grams <= 500) {
$cents = 320;
} elseif ($grams <= 2000) {
$cents = 560;
} else {
$startedKilos = intdiv($grams - 2000 + 999, 1000);
$cents = 560 + 110 * $startedKilos;
}
return $express ? $cents * 2 : $cents;
}
$n = (int) trim(fgets(STDIN));
for ($i = 0; $i < $n; $i++) {
[$grams, $flag] = explode(' ', trim(fgets(STDIN)));
$cents = postage((int) $grams, $flag === 'yes');
echo sprintf('%d.%02d', intdiv($cents, 100), $cents % 100), "\n";
}
Why it works
The function isolates the pricing rules from the input loop, so each part can be read and tested on its own. Returning integer cents is deliberate: 3.20 and 1.10 cannot be represented exactly as binary floats, and adding them repeatedly can produce a value a hair under 6.70 that then prints or compares wrongly. Integers never drift. Rounding up to a started kilogram is done with integer arithmetic too: add 999 before the integer division and any remainder pushes the result over the next boundary. The loop body only converts text to the types the function declares ((int) and === 'yes'), which is what typed parameters ask of the caller.
Lesson for this exercise: Functions in PHP