diff options
| -rw-r--r-- | challenge-323/packy-anderson/README.md | 2 | ||||
| -rw-r--r-- | challenge-323/packy-anderson/blog.txt | 1 | ||||
| -rwxr-xr-x | challenge-323/packy-anderson/elixir/ch-1.exs | 43 | ||||
| -rwxr-xr-x | challenge-323/packy-anderson/elixir/ch-2.exs | 89 | ||||
| -rwxr-xr-x | challenge-323/packy-anderson/perl/ch-1.pl | 32 | ||||
| -rwxr-xr-x | challenge-323/packy-anderson/perl/ch-2.pl | 57 | ||||
| -rwxr-xr-x | challenge-323/packy-anderson/python/ch-1.py | 33 | ||||
| -rwxr-xr-x | challenge-323/packy-anderson/python/ch-2.py | 62 | ||||
| -rwxr-xr-x | challenge-323/packy-anderson/raku/ch-1.raku | 31 | ||||
| -rwxr-xr-x | challenge-323/packy-anderson/raku/ch-2.raku | 54 |
10 files changed, 403 insertions, 1 deletions
diff --git a/challenge-323/packy-anderson/README.md b/challenge-323/packy-anderson/README.md index 766d853167..528307c718 100644 --- a/challenge-323/packy-anderson/README.md +++ b/challenge-323/packy-anderson/README.md @@ -23,4 +23,4 @@ ## Blog Post -[Perl Weekly Challenge: The array is rank, but the string is formatted](https://packy.dardan.com/b/VE) +[Perl Weekly Challenge: Should five percent appear too small...](https://packy.dardan.com/b/Ve) diff --git a/challenge-323/packy-anderson/blog.txt b/challenge-323/packy-anderson/blog.txt new file mode 100644 index 0000000000..812fe5334f --- /dev/null +++ b/challenge-323/packy-anderson/blog.txt @@ -0,0 +1 @@ +https://packy.dardan.com/b/Ve
\ No newline at end of file diff --git a/challenge-323/packy-anderson/elixir/ch-1.exs b/challenge-323/packy-anderson/elixir/ch-1.exs new file mode 100755 index 0000000000..711e1d33c0 --- /dev/null +++ b/challenge-323/packy-anderson/elixir/ch-1.exs @@ -0,0 +1,43 @@ +#!/usr/bin/env elixir + +defmodule PWC do + defp fmt(num) do + String.pad_leading(to_string(num), 2) + end + + def incDec([], x, explain), do: + {x, Enum.join(explain, "\n")} + + def incDec([op | operations], x, explain) do + old_x = x + {x, o} = cond do + String.contains?(op, "++") -> + { x + 1, "+" } + true -> + { x - 1, "-" } + end + incDec(operations, x, explain ++ [ + "Operation \"#{op}\" => #{fmt(old_x)} #{o} 1 => #{fmt(x)}" + ]) + end + + def incDec(operations) do + incDec(operations, 0, []) + end + + def solution(operations) do + display = "\"" <> Enum.join(operations, "\", \"") <> "\"" + IO.puts("Input: @operations = (#{display})") + {output, explain} = incDec(operations) + IO.puts("Output: #{output}\n\n#{explain}") + end +end + +IO.puts("Example 1:") +PWC.solution(["--x", "x++", "x++"]) + +IO.puts("\nExample 2:") +PWC.solution(["x++", "++x", "x++"]) + +IO.puts("\nExample 3:") +PWC.solution(["x++", "++x", "--x", "x--"]) diff --git a/challenge-323/packy-anderson/elixir/ch-2.exs b/challenge-323/packy-anderson/elixir/ch-2.exs new file mode 100755 index 0000000000..5321ca5897 --- /dev/null +++ b/challenge-323/packy-anderson/elixir/ch-2.exs @@ -0,0 +1,89 @@ +#!/usr/bin/env elixir + +defmodule PWC do + defp fmt(num) do + cond do + num == 0 -> + 0 # don't format a zero value + true -> + :erlang.float_to_binary(num, [decimals: 2]) + end + end + + defp plusJoin(arr), do: + Enum.join(arr, " + ") + + def taxAmt([], _, _, operations, subtotals, total) do + # there's no more brackets, return the summary + { + total, + "Total Tax => #{plusJoin(operations)}\n" <> + " => #{plusJoin(subtotals)}\n" <> + " => #{fmt(total)}" + } + end + + def taxAmt(_, income, _, operations, subtotals, total) + when income == 0 do + # there's no more income to tax, skip to the end + taxAmt([], 0, 0, operations, subtotals, total) + end + + def taxAmt([tax | remaining], income, last_max, operations, + subtotals, total) do + # the maximum amount to tax at this rate is the first + # element of the tax bracket; but we need to adjust this + # amount to be relative to the amount of last bracket + max = List.first(tax) - last_max + # the tax rate is the second element of the bracket + rate = List.last(tax) + # the amount to be taxed at this rate + amt = min(income, max) + # calculate the tax + tax = amt * rate/100 + + taxAmt( + remaining, + # we've just taxed amt, so remove it from income + income - amt, + # adjust the last rate for the next loop + max + last_max, + # save the steps so we can display them at the end + operations ++ ["(#{amt} * #{rate}/100)"], + # make sure we display to 100ths place + # if we hace a non-zero tax amount + subtotals ++ ["#{fmt(tax)}"], + total + tax + ) + end + + def taxAmt(income, tax) do + if income == 0 do + { 0, "" } # special case + else + taxAmt(tax, income, 0, [], [], 0) + end + end + + defp fmtArray(t, arr) do + arr = arr ++ [ "[#{List.first(t)},#{List.last(t)}]" ] + { t, arr } + end + + def solution(income, tax) do + {_, brackets} = Enum.map_reduce(tax, [], &fmtArray/2) + display = Enum.join(brackets, ", ") + IO.puts("Input: $income = #{income}, @tax = (#{display})") + {total, explain} = taxAmt(income, tax) + IO.puts("Output: #{total}\n\n#{explain}") + end +end + +IO.puts("Example 1:") +PWC.solution(10, [[3, 50], [7, 10], [12,25]]) + +IO.puts("\nExample 2:") +PWC.solution(2, [[1, 0], [4, 25], [5,50]]) + +IO.puts("\nExample 3:") +PWC.solution(0, [[2, 50],]) diff --git a/challenge-323/packy-anderson/perl/ch-1.pl b/challenge-323/packy-anderson/perl/ch-1.pl new file mode 100755 index 0000000000..3ec5d260c9 --- /dev/null +++ b/challenge-323/packy-anderson/perl/ch-1.pl @@ -0,0 +1,32 @@ +#!/usr/bin/env perl +use v5.40; + +sub incDec(@operations) { + my ($x, $old_x, $o) = (0, 0, q{}); + my @explain; + for my $op ( @operations ) { + $x = ($op =~ /\+\+/) ? $x + 1 : $x - 1; + $o = ($op =~ /\+\+/) ? '+' : '-'; + push @explain, + sprintf 'Operation "%s" => %2d %s 1 => %2d', + $op, $old_x, $o, $x + ; + $old_x = $x; + } + return ($x, join("\n", @explain)); +} + +sub solution($operations) { + say 'Input: @operations = ("' . join('", "', @$operations) . '")'; + my ($output, $explain) = incDec(@$operations); + say "Output: $output\n\n$explain"; +} + +say "Example 1:"; +solution(["--x", "x++", "x++"]); + +say "\nExample 2:"; +solution(["x++", "++x", "x++"]); + +say "\nExample 3:"; +solution(["x++", "++x", "--x", "x--"]); diff --git a/challenge-323/packy-anderson/perl/ch-2.pl b/challenge-323/packy-anderson/perl/ch-2.pl new file mode 100755 index 0000000000..1239856bf6 --- /dev/null +++ b/challenge-323/packy-anderson/perl/ch-2.pl @@ -0,0 +1,57 @@ +#!/usr/bin/env perl +use v5.40; + +use List::AllUtils qw( min sum ); + +sub taxAmt($income, @tax) { + return (0, "") if $income == 0; # special case + + my $last_max = 0; + my @operations; + my @subtotals; + for my $bracket (@tax) { + my($max, $rate) = @$bracket; + # adjust the maximum amount at this rate + # to be relative to the last rate + $max -= $last_max; + # the amount to be taxed at this rate + my $amt = min($income, $max); + my $tax = $amt * $rate/100; + # make sure we display to 100ths place + # if we hace a non-zero tax amount + $tax = sprintf '%0.2f', $tax if $tax > 0; + # save the steps so we can display them at the end + push @operations, "($amt * $rate/100)"; + push @subtotals, $tax; + # we've just taxed $amt, so remove it from $income + $income -= $amt; + # adjust the last rate for the next loop + $last_max += $max; + # bail if there's no more income + last if $income <= 0; + } + my $total = sum @subtotals; + $total = sprintf '%0.2f', $total if $total > 0; + my $explain = "Total Tax => " . join(' + ', @operations) . "\n" + . " => " . join(' + ', @subtotals) . "\n" + . " => $total"; + + return $total, $explain; +} + +sub solution($income, $tax) { + my @display = map { "[" . join(',', @$_) . "]" } @$tax; + say "Input: \$income = $income, " + . "\@tax = (" . join(', ', @display) . ")"; + my ($output, $explain) = taxAmt($income, @$tax); + say "Output: $output\n\n$explain"; +} + +say "Example 1:"; +solution(10, [[3, 50], [7, 10], [12,25]]); + +say "\nExample 2:"; +solution(2, [[1, 0], [4, 25], [5,50]]); + +say "\nExample 3:"; +solution(0, [[2, 50],]); diff --git a/challenge-323/packy-anderson/python/ch-1.py b/challenge-323/packy-anderson/python/ch-1.py new file mode 100755 index 0000000000..5cbccba4aa --- /dev/null +++ b/challenge-323/packy-anderson/python/ch-1.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python + +def incDec(operations): + x = 0 + old_x = 0 + o = '' + explain = [] + for op in operations: + x = x + 1 if "++" in op else x - 1 + o = '+' if "++" in op else '-' + explain.append( + 'Operation "{}" => {:2d} {} 1 => {:2d}'.format( + op, old_x, o, x + ) + ) + old_x = x + return x, "\n".join(explain) + +def solution(operations): + display = '"' + '", "'.join(operations) + '"' + print(f'Input: @operations = ({display})') + output, explain = incDec(operations) + print(f'Output: {output}\n\n{explain}') + + +print('Example 1:') +solution(["--x", "x++", "x++"]) + +print('\nExample 2:') +solution(["x++", "++x", "x++"]) + +print('\nExample 3:') +solution(["x++", "++x", "--x", "x--"]) diff --git a/challenge-323/packy-anderson/python/ch-2.py b/challenge-323/packy-anderson/python/ch-2.py new file mode 100755 index 0000000000..c5c646192d --- /dev/null +++ b/challenge-323/packy-anderson/python/ch-2.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +def fmt(num): + if num > 0: + # display to 100ths place + return '{:0.2f}'.format(num) + else: + # format it as a string + return f"{int(num)}" + +def taxAmt(income, tax): + if income == 0: + return 0, "" # special case + + last_max = 0 + total = 0 + operations = [] + subtotals = [] + for max_income, rate in tax: + # adjust the maximum amount at this rate + # to be relative to the last rate + max_income -= last_max + # the amount to be taxed at this rate + amt = min(income, max_income) + tax = amt * rate/100 + total += tax + # make sure we display to 100ths place + # if we hace a non-zero tax amount + tax = fmt(tax) + # save the steps so we can display them at the end + operations.append(f"({amt} * {rate}/100)") + subtotals.append(tax) + # we've just taxed $amt, so remove it from $income + income -= amt + # adjust the last rate for the next loop + last_max += max_income + # bail if there's no more income + if income <= 0: break + + return ( + total, + "Total Tax => " + ' + '.join(operations) + "\n" + + " => " + ' + '.join(subtotals) + "\n" + + " => " + fmt(total) + ) + +def solution(income, tax): + brackets = [ f"[{t[0]},{t[1]}]" for t in tax ] + display = ", ".join(brackets) + print(f'Input: $income = {income}, @tax = ({display})') + output, explain = taxAmt(income, tax) + print(f'Output: {output}\n\n{explain}') + + +print('Example 1:') +solution(10, [[3, 50], [7, 10], [12,25]]) + +print('\nExample 2:') +solution(2, [[1, 0], [4, 25], [5,50]]) + +print('\nExample 3:') +solution(0, [[2, 50],]) diff --git a/challenge-323/packy-anderson/raku/ch-1.raku b/challenge-323/packy-anderson/raku/ch-1.raku new file mode 100755 index 0000000000..213e6498c7 --- /dev/null +++ b/challenge-323/packy-anderson/raku/ch-1.raku @@ -0,0 +1,31 @@ +#!/usr/bin/env raku +use v6; + +sub incDec(@operations) { + my ($x, $old_x, $o) = (0, 0, q{}); + my @explain; + for @operations -> $op { + ($x, $o) = ($op ~~ /\+\+/) ?? ($x + 1, '+') !! ($x - 1, '-'); + @explain.push( + sprintf 'Operation "%s" => %2d %s 1 => %2d', + $op, $old_x, $o, $x + ); + $old_x = $x; + } + return ($x, @explain.join("\n")); +} + +sub solution(@operations) { + say 'Input: @operations = ("' ~ @operations.join('", "') ~ '")'; + my ($output, $explain) = incDec(@operations); + say "Output: $output\n\n$explain"; +} + +say "Example 1:"; +solution(["--x", "x++", "x++"]); + +say "\nExample 2:"; +solution(["x++", "++x", "x++"]); + +say "\nExample 3:"; +solution(["x++", "++x", "--x", "x--"]); diff --git a/challenge-323/packy-anderson/raku/ch-2.raku b/challenge-323/packy-anderson/raku/ch-2.raku new file mode 100755 index 0000000000..d5d2e3b63e --- /dev/null +++ b/challenge-323/packy-anderson/raku/ch-2.raku @@ -0,0 +1,54 @@ +#!/usr/bin/env raku +use v6; + +sub taxAmt($income is copy, @tax) { + return (0, "") if $income == 0; # special case + + my $last_max = 0; + my @operations; + my @subtotals; + for @tax -> ($max is copy, $rate) { + # adjust the maximum amount at this rate + # to be relative to the last rate + $max -= $last_max; + # the amount to be taxed at this rate + my $amt = min($income, $max); + my $tax = $amt * $rate/100; + # make sure we display to 100ths place + # if we hace a non-zero tax amount + $tax = sprintf '%0.2f', $tax if $tax > 0; + # save the steps so we can display them at the end + @operations.push("($amt * $rate/100)"); + @subtotals.push($tax); + # we've just taxed $amt, so remove it from $income + $income -= $amt; + # adjust the last rate for the next loop + $last_max += $max; + # bail if there's no more income + last if $income <= 0; + } + my $total = @subtotals.sum; + $total = sprintf '%0.2f', $total if $total > 0; + my $explain = "Total Tax => " ~ @operations.join(' + ') ~ "\n" + ~ " => " ~ @subtotals.join(' + ') ~ "\n" + ~ " => $total"; + + return $total, $explain; +} + +sub solution($income, @tax) { + my @display = @tax.map({ "[" ~ $_.join(',') ~ "]" }); + say "Input: \$income = $income, " + ~ "\@tax = (" ~ @display.join(', ') ~ ")"; + my ($output, $explain) = taxAmt($income, @tax); + say "Output: $output\n\n$explain"; +} + +say "Example 1:"; +solution(10, [[3, 50], [7, 10], [12,25]]); + +say "\nExample 2:"; +solution(2, [[1, 0], [4, 25], [5,50]]); + +say "\nExample 3:"; +solution(0, [[2, 50],]); |
