aboutsummaryrefslogtreecommitdiff
path: root/challenge-270
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2024-05-27 11:55:11 +0100
committerGitHub <noreply@github.com>2024-05-27 11:55:11 +0100
commit6316d6f47ce102f090a6ba18c5d5b4ac52bc2a82 (patch)
tree421c6e4cf7720581a9ca90bd7d9c16a2bebd0447 /challenge-270
parent7a80978d123027cd31180b1b9300b2a4e04dfada (diff)
parent733a760558ccbb030b2c7689a486247f105dd90b (diff)
downloadperlweeklychallenge-club-6316d6f47ce102f090a6ba18c5d5b4ac52bc2a82.tar.gz
perlweeklychallenge-club-6316d6f47ce102f090a6ba18c5d5b4ac52bc2a82.tar.bz2
perlweeklychallenge-club-6316d6f47ce102f090a6ba18c5d5b4ac52bc2a82.zip
Merge pull request #10158 from packy/master
Challenge 270 solutions by Packy Anderson
Diffstat (limited to 'challenge-270')
-rw-r--r--challenge-270/packy-anderson/README.md4
-rw-r--r--challenge-270/packy-anderson/blog.txt1
-rwxr-xr-xchallenge-270/packy-anderson/elixir/ch-1.exs75
-rwxr-xr-xchallenge-270/packy-anderson/elixir/ch-2.exs180
-rwxr-xr-xchallenge-270/packy-anderson/perl/ch-1.pl69
-rwxr-xr-xchallenge-270/packy-anderson/perl/ch-2.pl91
-rwxr-xr-xchallenge-270/packy-anderson/python/ch-1.py56
-rwxr-xr-xchallenge-270/packy-anderson/python/ch-2.py109
-rwxr-xr-xchallenge-270/packy-anderson/raku/ch-1.raku64
-rwxr-xr-xchallenge-270/packy-anderson/raku/ch-2.raku94
10 files changed, 742 insertions, 1 deletions
diff --git a/challenge-270/packy-anderson/README.md b/challenge-270/packy-anderson/README.md
index 3f65972d0f..bf39aceac0 100644
--- a/challenge-270/packy-anderson/README.md
+++ b/challenge-270/packy-anderson/README.md
@@ -11,13 +11,15 @@
* [Task 2](perl/ch-2.pl)
## Guest Language: Python
+
* [Task 1](python/ch-1.py)
* [Task 2](python/ch-2.py)
## Guest Language: Elixir
+
* [Task 1](elixir/ch-1.exs)
* [Task 2](elixir/ch-2.exs)
## Blog Post
-[Bitwise Distribution](https://packy.dardan.com/b/LS)
+[Elements are Special](https://packy.dardan.com/b/LX)
diff --git a/challenge-270/packy-anderson/blog.txt b/challenge-270/packy-anderson/blog.txt
new file mode 100644
index 0000000000..1fd039ca7b
--- /dev/null
+++ b/challenge-270/packy-anderson/blog.txt
@@ -0,0 +1 @@
+https://packy.dardan.com/b/LX \ No newline at end of file
diff --git a/challenge-270/packy-anderson/elixir/ch-1.exs b/challenge-270/packy-anderson/elixir/ch-1.exs
new file mode 100755
index 0000000000..abee770d6c
--- /dev/null
+++ b/challenge-270/packy-anderson/elixir/ch-1.exs
@@ -0,0 +1,75 @@
+#!/usr/bin/env elixir
+
+defmodule PWC do
+
+ def sumRow(matrix, i) do
+ matrix
+ |> Enum.at(i)
+ |> Enum.sum
+ end
+
+ def sumCol(matrix, j) do
+ matrix
+ |> Enum.map(fn x -> Enum.at(x, j) end)
+ |> Enum.sum
+ end
+
+ def specialPositions(matrix) do
+ special = []
+ special = for i <- 0..length(matrix)-1 do
+ row = Enum.at(matrix, i)
+ for j <- 0..length(row)-1 do
+ value = Enum.at(row, j)
+ if value == 1 and
+ sumRow(matrix, i) == 1 and
+ sumCol(matrix, j) == 1 do
+ # it's special
+ special ++ [ "(#{i}, #{j})" ]
+ else
+ special
+ end
+ end
+ end
+ special = List.flatten(special)
+ {
+ length(special),
+ case length(special) do
+ 1 -> "Special position is "
+ _ -> "Special positions are "
+ end <> Enum.join(special, ", ")
+ }
+ end
+
+ # default value for indent
+ def formatMatrix(matrix), do: formatMatrix(matrix, 17)
+
+ def formatMatrix(matrix, indent) do
+ output = for row <- matrix do
+ String.duplicate(" ", indent) <> " [" <>
+ Enum.join(row, ", ") <> "]"
+ end
+ "[\n" <> Enum.join(output, ",\n") <> "\n" <>
+ String.duplicate(" ", indent) <> "]"
+ end
+
+ def solution(matrix) do
+ IO.puts("Input: $matrix = " <> formatMatrix(matrix))
+ {count, explain} = PWC.specialPositions(matrix)
+ IO.puts("Output: " <> to_string(count) )
+ IO.puts("\n" <> explain)
+ end
+end
+
+IO.puts("Example 1:")
+PWC.solution([
+ [1,0,0],
+ [0,0,1],
+ [1,0,0]
+])
+
+IO.puts("\nExample 2:")
+PWC.solution([
+ [1,0,0],
+ [0,1,0],
+ [0,0,1]
+])
diff --git a/challenge-270/packy-anderson/elixir/ch-2.exs b/challenge-270/packy-anderson/elixir/ch-2.exs
new file mode 100755
index 0000000000..2904331718
--- /dev/null
+++ b/challenge-270/packy-anderson/elixir/ch-2.exs
@@ -0,0 +1,180 @@
+#!/usr/bin/env elixir
+
+defmodule PWC do
+ # get just the indices stored in the map of maps
+ defp indicesInMap(mapping) do
+ List.flatten( for i <- Map.values(mapping), do: Map.keys(i) )
+ end
+
+ def fmtInts(ints) do
+ "@ints = (" <> Enum.join(ints, ", ") <> ")"
+ end
+
+ def addToMap(mapping, intVal, i) do
+ submap = Map.put(Map.get(mapping, intVal, %{}), i, 1)
+ Map.put(mapping, intVal, submap)
+ end
+
+ def removeFromMap(mapping, intVal, i) do
+ submap = Map.delete(Map.get(mapping, intVal, %{}), i)
+ if submap == %{} do
+ Map.delete(mapping, intVal)
+ else
+ Map.put(mapping, intVal, submap)
+ end
+ end
+
+ # Increments a value in a list at a given index
+ def incrementAt(ints, index) do
+ ints
+ |> Enum.with_index() # produces tuples of {value, index}
+ |> Enum.map(fn
+ {val, ^index} -> val + 1 # ^ matches on index
+ {val, _} -> val
+ end)
+ end
+
+ # just remove the old value from the map
+ # if the new value is maxVal
+ def reMap(mapping, value, maxVal, index) when value == maxVal do
+ mapping |> removeFromMap(value - 1, index)
+ end
+
+ # if the number we incremented is less than the max,
+ # put it back in the mapping
+ def reMap(mapping, value, _, index) do
+ mapping
+ |> removeFromMap(value - 1, index)
+ |> addToMap(value, index)
+ end
+
+ # stopping case
+ defp equalize(params = %{indices: indices})
+ when length(indices) == 0, do: params
+
+ # level 2 case
+ defp equalize(params = %{indices: indices, x: x, y: y})
+ when length(indices) > 1 and x * 2 >= y do
+ {i, indices} = List.pop_at(indices, 0)
+ {j, _} = List.pop_at(indices, 0)
+ mapping = params[:mapping]
+ steps = params[:steps]
+ ints = params[:ints]
+
+ # increment the values
+ ints = incrementAt(ints, i)
+ ints = incrementAt(ints, j)
+ steps = steps ++ [
+ "Level 2: i=#{i}, j=#{j}, so $ints[#{i}] += 1 and " <>
+ "$ints[#{j}] += 1\n" <> fmtInts(ints)
+ ]
+ params = %{params | L2: params[:L2] + 1}
+
+ mapping = reMap(mapping, Enum.at(ints, i), params[:maxVal], i)
+ mapping = reMap(mapping, Enum.at(ints, j), params[:maxVal], j)
+ params = %{params |
+ indices: indicesInMap(mapping),
+ mapping: mapping,
+ steps: steps,
+ ints: ints
+ }
+ equalize(params)
+ end
+
+ # level 1 case
+ defp equalize(params = %{indices: indices}) do
+ {i, _} = List.pop_at(indices, 0)
+ mapping = params[:mapping]
+ steps = params[:steps]
+ ints = params[:ints]
+
+ # increment the values
+ ints = incrementAt(ints, i)
+ steps = steps ++ [
+ "Level 1: i=#{i}, so $ints[#{i}] += 1\n" <>
+ fmtInts(ints)
+ ]
+ params = %{params | L1: params[:L1] + 1}
+
+ mapping = reMap(mapping, Enum.at(ints, i), params[:maxVal], i)
+ params = %{params |
+ indices: indicesInMap(mapping),
+ mapping: mapping,
+ steps: steps,
+ ints: ints
+ }
+ equalize(params)
+ end
+
+ # once the list of ints is empty, return the results
+ defp makeMapping([], maxVal, mapping, _), do: {maxVal, mapping}
+
+ # process the first int off the list and recurse to
+ # process the rest
+ defp makeMapping([intVal | ints], maxVal, mapping, index) do
+ maxVal = Enum.max([intVal, maxVal])
+ mapping = addToMap(mapping, intVal, index)
+ makeMapping(ints, maxVal, mapping, index + 1)
+ end
+
+ defp inflectTimes(n) do
+ case n do
+ 1 -> "time"
+ _ -> "times"
+ end
+ end
+
+ defp equalizeArray(ints, x, y) do
+ {maxVal, mapping} = makeMapping(ints, -1, %{}, 0)
+ # we don't need to operate on values already at the max
+ mapping = Map.delete(mapping, maxVal)
+
+ params = equalize(%{
+ indices: indicesInMap(mapping),
+ mapping: mapping,
+ maxVal: maxVal,
+ steps: [],
+ ints: ints,
+ L1: 0,
+ L2: 0,
+ x: x,
+ y: y,
+ })
+ steps = params[:steps]
+ l1 = params[:L1]
+ l2 = params[:L2]
+
+ cost = (l1 * x) + (l2 * y)
+ operations = if l1 > 0 do
+ [ "Level 1, #{l1} " <> inflectTimes(l1) ]
+ else
+ []
+ end
+ operations = if l2 > 0 do
+ operations ++ [ "Level 2, #{l2} " <> inflectTimes(l2) ]
+ else
+ operations
+ end
+ steps = steps ++ [
+ "We performed operation " <>
+ Enum.join(operations, " and ") <>
+ "\nSo the total cost would be " <>
+ "(#{l1} × $x) + (#{l2} × $y) => " <>
+ "(#{l1} × #{x}) + (#{l2} × #{y}) => #{cost}"
+ ]
+ { cost, Enum.join(steps, "\n\n") }
+ end
+
+ def solution(ints, x, y) do
+ IO.puts("Input: " <> fmtInts(ints) <> ", $x = #{x}, $y = #{y}")
+ {cost, steps} = equalizeArray(ints, x, y)
+ IO.puts("Output: " <> to_string(cost) )
+ IO.puts("\n" <> steps)
+ end
+end
+
+IO.puts("Example 1:")
+PWC.solution([4,1], 3, 2)
+
+IO.puts("\nExample 2:")
+PWC.solution([2, 3, 3, 3, 5], 2, 1)
diff --git a/challenge-270/packy-anderson/perl/ch-1.pl b/challenge-270/packy-anderson/perl/ch-1.pl
new file mode 100755
index 0000000000..a819a416eb
--- /dev/null
+++ b/challenge-270/packy-anderson/perl/ch-1.pl
@@ -0,0 +1,69 @@
+#!/usr/bin/env perl
+use v5.38;
+
+use List::Util qw( sum );
+use Lingua::EN::Inflexion qw( wordlist );
+
+sub sumRow($matrix, $i) {
+ return sum @{ $matrix->[$i] };
+}
+
+sub sumCol($matrix, $j) {
+ return sum map { $_->[$j] } @$matrix;
+}
+
+sub specialPositions(@matrix) {
+ my @special;
+ foreach my $i ( 0 .. $#matrix ) {
+ my @row = @{$matrix[$i]};
+ foreach my $j ( 0 .. $#row ) {
+ my $value = $row[$j];
+ # not special unless = 1
+ next unless $value == 1;
+ # not special unless only 1 in row
+ next unless sumRow(\@matrix, $i) == 1;
+ # not special unless only 1 in column
+ next unless sumCol(\@matrix, $j) == 1;
+ # it's special!
+ push @special, "($i, $j)";
+ }
+ }
+ my $list = wordlist(@special, { sep => ',' });
+ my $explain = 'Special position';
+ $explain .= (@special == 1) ? ' is ' : 's are ';
+ $explain .= $list;
+ return scalar(@special), $explain;
+}
+
+sub formatMatrix($matrix, $indent=17) {
+ my @output;
+ foreach my $row (@$matrix) {
+ my $output_row = q{ } x $indent . " [";
+ $output_row .= join(', ', map { sprintf "%1d", $_ } @$row) . ']';
+ push @output, $output_row;
+ }
+ return "[\n"
+ . join(",\n", @output)
+ . "\n"
+ . q{ } x $indent . "]";
+}
+
+sub solution($matrix) {
+ say 'Input: $matrix = ' . formatMatrix($matrix);
+ my ($count, $explain) = specialPositions(@$matrix);
+ say "Output: $count\n\n$explain";
+}
+
+say "Example 1:";
+solution([
+ [1,0,0],
+ [0,0,1],
+ [1,0,0]
+]);
+
+say "\nExample 2:";
+solution([
+ [1,0,0],
+ [0,1,0],
+ [0,0,1]
+]);
diff --git a/challenge-270/packy-anderson/perl/ch-2.pl b/challenge-270/packy-anderson/perl/ch-2.pl
new file mode 100755
index 0000000000..80a8887bbe
--- /dev/null
+++ b/challenge-270/packy-anderson/perl/ch-2.pl
@@ -0,0 +1,91 @@
+#!/usr/bin/env perl
+use v5.38;
+
+use List::Util qw( min );
+
+sub fmtInts(@ints) {
+ return '@ints = (' . join(', ', @ints) . ')';
+}
+
+sub getNextIndex($mapping) {
+ my $min = min(keys %$mapping); # note the current min val
+ my $i = min(keys %{$mapping->{$min}}); # get the smallest index
+ delete $mapping->{$min}{$i}; # remove index from map
+ unless (values %{$mapping->{$min}}) { # no more of this value
+ delete $mapping->{$min}; # remove value from map
+ }
+ return $i; # return the index
+}
+
+sub equalizeArray($ints, $x, $y) {
+ # track how many of each op, and terminal value
+ my $max = -Inf;
+ my %mapping;
+ my @steps;
+ my ($L1, $L2) = (0, 0);
+ # loop over the array to determine max value
+ # and where the lower numbers are
+ foreach my $i ( 0 .. $#{$ints} ) {
+ my $int = $ints->[$i];
+ $max = $int if ($int > $max);
+ $mapping{$int}{$i} = 1;
+ }
+ # we don't need to operate on values already at the max
+ delete $mapping{$max};
+
+ while (keys %mapping) {
+ my $elems = scalar(map { keys %$_ } values %mapping);
+ if ($elems > 1 && $x * 2 >= $y) {
+ # get the two indices
+ my $i = getNextIndex(\%mapping);
+ my $j = getNextIndex(\%mapping);
+
+ # increment the values
+ $ints->[$i]++;
+ $ints->[$j]++;
+ push @steps,
+ "Level 2: i=$i, j=$j, so \$ints[$i] += 1 and " .
+ "\$ints[$j] += 1\n" . fmtInts(@$ints);
+ $L2++;
+ # if the numbers we incremented are less than the max,
+ # put them back in the mapping
+ $mapping{$ints->[$i]}{$i} = 1 if ($ints->[$i] < $max);
+ $mapping{$ints->[$j]}{$j} = 1 if ($ints->[$j] < $max);
+ }
+ else {
+ # get the index
+ my $i = getNextIndex(\%mapping);
+ # increment the value
+ $ints->[$i]++;
+ push @steps, "Level 1: i=$i, so \$ints[$i] += 1\n" .
+ fmtInts(@$ints);
+ $L1++;
+ # if the number we incremented is less than the max,
+ # put it back in the mapping
+ $mapping{$ints->[$i]}{$i} = 1 if ($ints->[$i] < $max);
+ }
+ }
+ my $cost = ($L1 * $x) + ($L2 * $y);
+ my @operations;
+ push @operations, "Level 1, $L1 " . ($L1 == 1 ? 'time' : 'times')
+ if $L1;
+ push @operations, "Level 2, $L2 " . ($L2 == 1 ? 'time' : 'times')
+ if $L2;
+ push @steps,
+ 'We performed operation ' . join(" and ", @operations) .
+ "\nSo the total cost would be ($L1 × \$x) + ($L2 × \$y) => " .
+ "($L1 × $x) + ($L2 × $y) => $cost";
+ return $cost, join("\n\n", @steps);
+}
+
+sub solution($ints, $x, $y) {
+ say 'Input: ' . fmtInts(@$ints) . ", \$x = $x and \$y = $y";
+ my ($cost, $steps) = equalizeArray($ints, $x, $y);
+ say "Output: $cost\n\n$steps";
+}
+
+say "Example 1:";
+solution([4,1], 3, 2);
+
+say "\nExample 2:";
+solution([2, 3, 3, 3, 5], 2, 1);
diff --git a/challenge-270/packy-anderson/python/ch-1.py b/challenge-270/packy-anderson/python/ch-1.py
new file mode 100755
index 0000000000..1aed4639f5
--- /dev/null
+++ b/challenge-270/packy-anderson/python/ch-1.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+
+def sumRow(matrix, i):
+ return sum(matrix[i])
+
+def sumCol(matrix, j):
+ return sum([ i[j] for i in matrix ])
+
+def specialPositions(matrix):
+ special = []
+ for i, row in enumerate(matrix):
+ for j, value in enumerate(row):
+ # not special unless = 1
+ if (value == 1 and
+ # not special unless only 1 in row
+ sumRow(matrix, i) == 1 and
+ # not special unless only 1 in column
+ sumCol(matrix, j) == 1):
+ # it's special!
+ special.append( f"({i}, {j})" )
+ explain = 'Special position'
+ explain += ' is ' if len(special) == 1 else 's are '
+ explain += ', '.join(special)
+ return len(special), explain
+
+def formatMatrix(matrix, indent=17):
+ output = []
+ for row in matrix:
+ output_row = ' ' * indent + ' ['
+ output_row += ', '.join(map(lambda i: str(i), row))
+ output_row += ']'
+ output.append(output_row)
+
+ return(
+ "[\n" + ",\n".join(output) + "\n" +
+ ' ' * indent + ']'
+ )
+
+def solution(matrix):
+ print(f'Input: $matrix = {formatMatrix(matrix)}')
+ count, explain = specialPositions(matrix)
+ print(f'Output: {count}\n\n{explain}')
+
+print('Example 1:')
+solution([
+ [1,0,0],
+ [0,0,1],
+ [1,0,0]
+])
+
+print('\nExample 2:')
+solution([
+ [1,0,0],
+ [0,1,0],
+ [0,0,1]
+]) \ No newline at end of file
diff --git a/challenge-270/packy-anderson/python/ch-2.py b/challenge-270/packy-anderson/python/ch-2.py
new file mode 100755
index 0000000000..94a874ac2c
--- /dev/null
+++ b/challenge-270/packy-anderson/python/ch-2.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python
+
+import sys
+
+def items_in_dict(d):
+ items = 0
+ for v, d2 in d.items():
+ for i in d2.keys():
+ items += 1
+ return items
+
+def comma_join(arr):
+ return ', '.join(map(lambda i: str(i), arr))
+
+def fmtInts(ints):
+ return f'@ints = ({comma_join(ints)})'
+
+def setMap(mapping, intVal, i):
+ if mapping.get(intVal, None) is None:
+ mapping[intVal] = {}
+ mapping[intVal][i] = 1
+
+def getNextIndex(mapping):
+ minVal = min(mapping.keys()) # note the current min val
+ i = min(mapping[minVal].keys()) # minimum index for that val
+ del mapping[minVal][i] # remove index from map
+ if not mapping[minVal].values(): # no more of this value
+ del mapping[minVal] # remove value from map
+ return i # return the index
+
+def equalizeArray(ints, x, y):
+ # track how many of each op, and terminal value
+ maxVal = -1 * sys.maxsize
+ mapping = {}
+ steps = []
+ L1 = 0
+ L2 = 0
+ # loop over the array to determine max value
+ # and where the lower numbers are
+ for i, intVal in enumerate(ints):
+ if intVal > maxVal:
+ maxVal = intVal
+ setMap(mapping, intVal, i)
+
+ # we don't need to operate on values already at the max
+ del mapping[maxVal]
+
+ while mapping.keys():
+ if items_in_dict(mapping) > 1 and x * 2 >= y:
+ # get the two indices
+ i = getNextIndex(mapping)
+ j = getNextIndex(mapping)
+
+ # increment the values
+ ints[i] += 1
+ ints[j] += 1
+ steps.append(
+ f"Level 2: i={i}, j={j}, so $ints[{i}] += 1 and " +
+ f"$ints[{j}] += 1\n" + fmtInts(ints)
+ )
+ L2 += 1
+ # if the numbers we incremented are less than the max,
+ # put them back in the mapping
+ if ints[i] < maxVal:
+ setMap(mapping, ints[i], i)
+ if ints[j] < maxVal:
+ setMap(mapping, ints[j], j)
+ else:
+ # get the index
+ i = getNextIndex(mapping)
+ # increment the value
+ ints[i] += 1
+ steps.append(
+ f"Level 1: i={i}, so $ints[{i}] += 1\n" +
+ fmtInts(ints)
+ )
+ L1 += 1
+ # if the number we incremented is less than the max,
+ # put it back in the mapping
+ if ints[i] < maxVal:
+ setMap(mapping, ints[i], i)
+
+ cost = (L1 * x) + (L2 * y)
+ operations = []
+ if L1:
+ operations.append(
+ f"Level 1, {L1} " + ('time' if L1 == 1 else 'times')
+ )
+ if L2:
+ operations.append(
+ f"Level 2, {L2} " + ('time' if L2 == 1 else 'times')
+ )
+ steps.append(
+ 'We performed operation ' + ' and '.join(operations) +
+ f"\nSo the total cost would be ({L1} × $x) + ({L2} × $y) => " +
+ f"({L1} × {x}) + ({L2} × {y}) => {cost}"
+ )
+ return cost, "\n\n".join(steps)
+
+def solution(ints, x, y):
+ print(f'Input: {fmtInts(ints)}, $x = {x}, $y = {y}')
+ cost, steps = equalizeArray(ints, x, y)
+ print(f'Output: {cost}\n\n{steps}')
+
+print('Example 1:')
+solution([4,1], 3, 2)
+
+print('\nExample 2:')
+solution([2, 3, 3, 3, 5], 2, 1)
diff --git a/challenge-270/packy-anderson/raku/ch-1.raku b/challenge-270/packy-anderson/raku/ch-1.raku
new file mode 100755
index 0000000000..39c335e748
--- /dev/null
+++ b/challenge-270/packy-anderson/raku/ch-1.raku
@@ -0,0 +1,64 @@
+#!/usr/bin/env raku
+use v6;
+
+use Lingua::Conjunction;
+
+sub sumRow(@matrix, $i) {
+ return [+] @matrix[$i].values;
+}
+
+sub sumCol(@matrix, $j) {
+ return [+] ( @matrix.map: { .[$j] } );
+}
+
+sub specialPositions(@matrix) {
+ my @special;
+ for @matrix.kv -> $i, @row {
+ for @row.kv -> $j, $value {
+ # not special unless = 1
+ next unless $value == 1;
+ # not special unless only 1 in row
+ next unless sumRow(@matrix, $i) == 1;
+ # not special unless only 1 in column
+ next unless sumCol(@matrix, $j) == 1;
+ # it's special!
+ @special.push( "($i, $j)" );
+ }
+ }
+ my $str = 'Special position[|s] [is|are] |list|';
+ return @special.elems, conjunction(@special, :$str, :alt<,>);
+}
+
+sub formatMatrix(@matrix, $indent=17) {
+ my @output;
+ for @matrix -> @row {
+ my $output_row = q{ } x $indent ~ " [";
+ $output_row ~= @row.map({ sprintf "%1d", $_ })
+ .join(', ') ~ "]";
+ @output.push($output_row);
+ }
+ return "[\n"
+ ~ @output.join(",\n")
+ ~ "\n"
+ ~ q{ } x $indent ~ "]";
+}
+
+sub solution(@matrix) {
+ say 'Input: $matrix = ' ~ formatMatrix(@matrix);
+ my ($count, $explain) = specialPositions(@matrix);
+ say "Output: $count\n\n$explain";
+}
+
+say "Example 1:";
+solution([
+ [1,0,0],
+ [0,0,1],
+ [1,0,0]
+]);
+
+say "\nExample 2:";
+solution([
+ [1,0,0],
+ [0,1,0],
+ [0,0,1]
+]);
diff --git a/challenge-270/packy-anderson/raku/ch-2.raku b/challenge-270/packy-anderson/raku/ch-2.raku
new file mode 100755
index 0000000000..897ddc89a2
--- /dev/null
+++ b/challenge-270/packy-anderson/raku/ch-2.raku
@@ -0,0 +1,94 @@
+#!/usr/bin/env raku
+use v6;
+
+sub fmtInts(@ints) {
+ return '@ints = (' ~ @ints.join(', ') ~ ')';
+}
+
+sub getNextIndex(%mapping) {
+ my $min = min(%mapping.keys); # note the current min val
+ my $i = min(%mapping{$min}.keys); # get the smallest index
+ %mapping{$min}{$i}:delete; # remove index from map
+ unless (%mapping{$min}.values) { # no more of this value
+ %mapping{$min}:delete; # remove value from map
+ }
+ return $i; # return the index
+}
+
+sub equalizeArray(@ints, $x, $y) {
+ # track how many of each op, and terminal value
+ my $max = -Inf;
+ my %mapping;
+ my @steps;
+ my ($L1, $L2) = (0, 0);
+ # loop over the array to determine max value
+ # and where the lower numbers are
+ for @ints.kv -> $i, $int {
+ $max = $int if ($int > $max);
+ %mapping{$int}{$i} = 1;
+ }
+ # we don't need to operate on values already at the max
+ %mapping{$max}:delete;
+
+ while (%mapping.keys) {
+ my $elems = %mapping.values».List.flat.elems;
+ if ($elems > 1 && $x * 2 >= $y) {
+ # get the two indices
+ my $i = getNextIndex(%mapping);
+ my $j = getNextIndex(%mapping);
+
+ # increment the values
+ @ints[$i]++;
+ @ints[$j]++;
+ @steps.push(
+ "Level 2: i=$i, j=$j, so \$ints[$i] += 1 and " ~
+ "\$ints[$j] += 1\n" ~ fmtInts(@ints)
+ );
+ $L2++;
+ # if the numbers we incremented are less than the max,
+ # put them back in the mapping
+ %mapping{@ints[$i]}{$i} = 1 if (@ints[$i] < $max);
+ %mapping{@ints[$j]}{$j} = 1 if (@ints[$j] < $max);
+ }
+ else {
+ # get the index
+ my $i = getNextIndex(%mapping);
+ # increment the value
+ @ints[$i]++;
+ @steps.push(
+ "Level 1: i=$i, so \$ints[$i] += 1\n" ~
+ fmtInts(@ints)
+ );
+ $L1++;
+ # if the number we incremented is less than the max,
+ # put it back in the mapping
+ %mapping{@ints[$i]}{$i} = 1 if (@ints[$i] < $max);
+ }
+ }
+ my $cost = ($L1 * $x) + ($L2 * $y);
+ my @operations;
+ @operations.push(
+ "Level 1, $L1 " ~ ($L1 == 1 ?? 'time' !! 'times')
+ ) if $L1;
+ @operations.push(
+ "Level 2, $L2 " ~ ($L2 == 1 ?? 'time' !! 'times')
+ ) if $L2;
+ @steps.push(
+ 'We performed operation ' ~ @operations.join(" and ") ~
+ "\nSo the total cost would be ($L1 × \$x) + ($L2 × \$y) => " ~
+ "($L1 × $x) + ($L2 × $y) => $cost"
+ );
+ return $cost, @steps.join("\n\n");
+}
+
+sub solution(@ints, $x, $y) {
+ say 'Input: ' ~ fmtInts(@ints) ~ ", \$x = $x and \$y = $y";
+ my ($cost, $steps) = equalizeArray(@ints, $x, $y);
+ say "Output: $cost\n\n$steps";
+}
+
+say "Example 1:";
+solution([4,1], 3, 2);
+
+say "\nExample 2:";
+solution([2, 3, 3, 3, 5], 2, 1);