Perl Weekly Challenge 323.

My solutions (task 1 and task 2 ) to the The Weekly Challenge - 323.

Task 1: Increment Decrement

Submitted by: Mohammad Sajid Anwar
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

For the short answer I’ll ignore the actual name of the variable that is being incremented and decremented and I’ll assume the input is well formed. Thus, I only have to count how many increment and decrement operators there are and subtract them. The result fits a half-liner.

Example 1:

perl -E '
say "@ARGV -> ", (grep{/\+\+/}@ARGV)-(grep{/--/}@ARGV);
' -- --x x++ x++

Results:

--x x++ x++ -> 1

Example 2:

perl -E '
say "@ARGV -> ", (grep{/\+\+/}@ARGV)-(grep{/--/}@ARGV);
' -- x++ ++x x++

Results:

x++ ++x x++ -> 3

Example 3:

perl -E '
say "@ARGV -> ", (grep{/\+\+/}@ARGV)-(grep{/--/}@ARGV);
' --  x++ ++x --x x--

Results:

x++ ++x --x x-- -> 0

For the full code it would be more interesting if I allow different variables to be incremented/decremented. For simplicity I’ll assume variable names contain only alphabetical characters.

 1  # Perl weekly challenge 323
 2  # Task 1:
 3  #
 4  # See https://wlmb.github.io/2025/05/26/PWC323/#task-1-
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV;
 7      Usage: $0 E1 E2...
 8      to apply increment and decrement expressions ~En~
 9      of the form ++x, x++ --x, x--
10      where x is the name of a variable
11      FIN
12  my %vars;
13  for(@ARGV){
14      $vars{$1}//=0, $vars{$1}++, next if /^\+\+([[:alpha:]]+)$/;
15      $vars{$1}//=0, $vars{$1}--, next if /^--([[:alpha:]]+)$/;
16      $vars{$1}//=0, $vars{$1}++, next if /^([[:alpha:]]+)\+\+$/;
17      $vars{$1}//=0, $vars{$1}--, next if /^([[:alpha:]]+)--$/;
18      die "Wrong format: $_";
19  }
20  print "@ARGV -> ";
21  print "$_=$vars{$_} " for keys %vars;
22  print "\n";

Examples:

./ch-1.pl --x x++ x++
./ch-1.pl x++ ++x x++
./ch-1.pl x++ ++x --x x--

Results:

--x x++ x++ -> x=1
x++ ++x x++ -> x=3
x++ ++x --x x-- -> x=0

Example with more variables:

./ch-1.pl --x y++ z++ x++ ++y ++z x++ y++ --z z--

Results:

--x y++ z++ x++ ++y ++z x++ y++ --z z-- -> y=3 x=1 z=0

Task 2: Tax Amount

Submitted by: Mohammad Sajid Anwar
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: 1.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

In the first example, the lowest incomes gets the highest tax, and the highest incomes, those above the last bracket, are not taxed at all. This strange scheme is becomming common! I would have expected a last bracket without an upper bound. But anyway, to solve the problem I have to find how much of the income is within each bracket and tax it accordingly. The code fits a two liner:

Example 1:

perl -MList::Util=min -E '
print "I=", $x=$i=shift, " tax=";$l=0;for my($h,$p)(@ARGV){print "[$h,$p]";
$r=$h-$l;$l=$h;next if $x<0;$q=min($x,$r);$t+=$q*$p/100;$x-=$q}say "-> $t";
' 10 3 50 7 10 12 25

Results:

I=10 tax=[3,50][7,10][12,25]-> 2.65

Example 2:

perl -MList::Util=min -E '
print "I=", $x=$i=shift, " tax=";$l=0;for my($h,$p)(@ARGV){print "[$h,$p]";
$r=$h-$l;$l=$h;next if $x<0;$q=min($x,$r);$t+=$q*$p/100;$x-=$q}say "-> $t";
' 2 1 0 4 25 5 50

Results:

I=2 tax=[1,0][4,25][5,50]-> 0.25

Example 3:

perl -MList::Util=min -E '
print "I=", $x=$i=shift, " tax=";$l=0;for my($h,$p)(@ARGV){print "[$h,$p]";
$r=$h-$l;$l=$h;next if $x<0;$q=min($x,$r);$t+=$q*$p/100;$x-=$q}say "-> $t";
' 0 2 50

Results:

I=0 tax=[2,50]-> 0

The full code is:

 1  # Perl weekly challenge 323
 2  # Task 2:  Tax Amount
 3  #
 4  # See https://wlmb.github.io/2025/05/26/PWC323/#task-2-tax-amount
 5  use v5.36;
 6  use List::Util qw(min);
 7  die <<~"FIN" unless @ARGV && @ARGV%2==1;
 8      Usage: $0 I M1 P1 M2 P2...
 9      to compute taxes corresponding to income I where Mn is the maximum
10      income in bracket n which is taxed with a percentage Pn
11      FIN
12  my $income = shift;
13  my $low = 0; # lowest bound of current bracket
14  my @tax;
15  my $result=0;
16  my $remaining = $income;
17  for my ($high, $percentage)(@ARGV){
18      push @tax, [$high, $percentage];
19      my $range=$high-$low;
20      $low=$high; # update for next iteration
21      next if $remaining < 0;
22      my $taxable = min($remaining, $range);
23      $result += $taxable*$percentage/100;
24      $remaining -= $taxable;
25  }
26  say "income=$income, tax=", join(", ", map{"[@$_]"} @tax)," -> $result";

Example:

./ch-2.pl 10 3 50 7 10 12 25
./ch-2.pl 2 1 0 4 25 5 50
./ch-2.pl 0 2 50

Results:

income=10, tax=[3 50], [7 10], [12 25] -> 2.65
income=2, tax=[1 0], [4 25], [5 50] -> 0.25
income=0, tax=[2 50] -> 0
Written on May 26, 2025