Perl Weekly Challenge: Week 323
Challenge 1:
Increment Decrement
You are given a list of operations.
Write a script to return the final value after performing the given operations in order. The initial value is always 0.
Possible Operations:
++x or x++: increment by 1
--x or x--: decrement by 1
Example 1
Input: @operations = ("--x", "x++", "x++")
Output: 1
Operation "--x" => 0 - 1 => -1
Operation "x++" => -1 + 1 => 0
Operation "x++" => 0 + 1 => 1
Example 2
Input: @operations = ("x++", "++x", "x++")
Output: 3
Example 3
Input: @operations = ("x++", "++x", "--x", "x--")
Output: 0
Operation "x++" => 0 + 1 => 1
Operation "++x" => 1 + 1 => 2
Operation "--x" => 2 - 1 => 1
Operation "x--" => 1 - 1 => 0
All we need to do for this one is to check if an operation contains ++
or --
. The position doesn't matter nor, at least for
the examples, does the name of the variable which is being incremented/decremented.
The total is initially set to 0.
my $total = 0;
For each operation, we check for increment or decrement with regular expressions and $total
is adjusted accordingly.
for @operations -> $operation {
if $operation ~~ /\+\+/ {
$total++;
}
if $operation ~~ /\-\-/ {
$total--;
}
}
The final value of $total
is printed.
say $total;
The Perl version works the same way.
my $total = 0;
for my $operation (@operations) {
if ($operation =~ /\+\+/) {
$total++;
}
if ($operation =~ /\-\-/) {
$total--;
}
}
say $total;
Challenge 2:
Tax Amount
You are given an income amount and tax brackets.
Write a script to calculate the total tax amount.
Example 1
Input: $income = 10, @tax = ([3, 50], [7, 10], [12,25])
Output: 2.65
1st tax bracket upto 3, tax is 50%.
2nd tax bracket upto 7, tax is 10%.
3rd tax bracket upto 12, tax is 25%.
Total Tax => (3 * 50/100) + (4 * 10/100) + (3 * 25/100)
=> 1.50 + 0.40 + 0.75
=> 2.65
Example 2
Input: $income = 2, @tax = ([1, 0], [4, 25], [5,50])
Output: 0.25
Total Tax => (1 * 0/100) + (1 * 25/100)
=> 0 + 0.25
=> 0.25
Example 3
Input: $income = 0, @tax = ([2, 50])
Output: 0
Sometimes, the hardest part of doing these problems is finding a good way to get the input into the script.
I have chosen to use a series of command-line arguments where the first is the income and the rest are tax
rate information as strings containing the bracket boundary and the taxation percentage seperated by white space.
So for example 1: 10 "3 50" "7 10" "12 25"
First, we set up a variable to track how much of $income
has been taxed.
my $taxed = 0;
Next we take the @tax
information and convert it into a Hash
where the keys are bracket boundaries, and the values
are the percentages. This can be done very handily with a .map()
which splits each rate string into two with .words()
and
converts it into a key-value Pair
with [=>]
.
my %taxes = @tax.map({ [=>] $_.words });
We also need to keep track of the total amount of tax levied so far.
my $total = 0;
Now for each bracket (sorted in ascending numeric order...)
for %taxes.keys.sort({$^a <=> $^b }) -> $bracket {
...If the amount that has been taxed is greater or equal to $income
we can stop processing.
if $taxed >= $income {
last;
}
Otherwise the amount to tax is calculated. If the bracket is greater than $income
, it is the $income
minus the
amount already taxed otherwise it is the bracket boundary minus the amount already taxed.
my $tax = ($bracket > $income ?? $income !! $bracket) - $taxed;
In either case this amount is added to $taxed
.
$taxed += $tax;
And how tax has to be paid on this amount is calculated and added to $total
.
$total += $tax * (%taxes{$bracket} / 100);
}
Finally we print $total
.
say $total;
In retrospect I should have made the variable names more descriptive but the algorithm is pretty good I think.
For Perl, the solution is much the same.
my $taxed = 0;
Expect perhaps this line which is slightly less concise and elegant as its' Raku equivalent.
my %taxes = map { my ($k, $v) = split /\s+/, $_; $k => $v } @tax;
my $total = 0;
for my $bracket ( sort { $a <=> $b } keys %taxes ) {
if ($taxed >= $income) {
last;
}
my $tax = ($bracket > $income ? $income : $bracket) - $taxed;
$taxed += $tax;
$total += $tax * ($taxes{$bracket} / 100);
}
say $total;