aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMohammad Sajid Anwar <Mohammad.Anwar@yahoo.com>2025-08-25 01:39:16 +0100
committerGitHub <noreply@github.com>2025-08-25 01:39:16 +0100
commit04effbcfe73b2cd29ae73182756f53012692e6f9 (patch)
treef8c6d9a510eeed7a57588f831284d60df40012a1
parent5c71e1ef11ec1d5fce6fd6d0d3ea3230e3d82b68 (diff)
parentce434c84f0f22e8284442ba44324842795d868e4 (diff)
downloadperlweeklychallenge-club-04effbcfe73b2cd29ae73182756f53012692e6f9.tar.gz
perlweeklychallenge-club-04effbcfe73b2cd29ae73182756f53012692e6f9.tar.bz2
perlweeklychallenge-club-04effbcfe73b2cd29ae73182756f53012692e6f9.zip
Merge pull request #12560 from packy/master
Challenge 335 solutions by Packy Anderson
-rw-r--r--challenge-335/packy-anderson/README.md2
-rw-r--r--challenge-335/packy-anderson/blog.txt1
-rwxr-xr-xchallenge-335/packy-anderson/elixir/ch-1.exs58
-rwxr-xr-xchallenge-335/packy-anderson/elixir/ch-2.exs123
-rwxr-xr-xchallenge-335/packy-anderson/perl/ch-1.pl36
-rwxr-xr-xchallenge-335/packy-anderson/perl/ch-2.pl85
-rwxr-xr-xchallenge-335/packy-anderson/python/ch-1.py42
-rwxr-xr-xchallenge-335/packy-anderson/python/ch-2.py76
-rwxr-xr-xchallenge-335/packy-anderson/raku/ch-1.raku29
-rwxr-xr-xchallenge-335/packy-anderson/raku/ch-2.raku81
10 files changed, 532 insertions, 1 deletions
diff --git a/challenge-335/packy-anderson/README.md b/challenge-335/packy-anderson/README.md
index 4b48fc6b17..83462935ff 100644
--- a/challenge-335/packy-anderson/README.md
+++ b/challenge-335/packy-anderson/README.md
@@ -23,4 +23,4 @@
## Blog Post
-[Perl Weekly Challenge: SUMone tell me what makes a point VALID?](https://packy.dardan.com/b/_1)
+[Perl Weekly Challenge: Fanfare for the Common Character](https://packy.dardan.com/b/_V)
diff --git a/challenge-335/packy-anderson/blog.txt b/challenge-335/packy-anderson/blog.txt
new file mode 100644
index 0000000000..7965881326
--- /dev/null
+++ b/challenge-335/packy-anderson/blog.txt
@@ -0,0 +1 @@
+https://packy.dardan.com/b/_V \ No newline at end of file
diff --git a/challenge-335/packy-anderson/elixir/ch-1.exs b/challenge-335/packy-anderson/elixir/ch-1.exs
new file mode 100755
index 0000000000..95696b4fe2
--- /dev/null
+++ b/challenge-335/packy-anderson/elixir/ch-1.exs
@@ -0,0 +1,58 @@
+#!/usr/bin/env elixir
+
+defmodule PWC do
+ def bag(word) do
+ {_, bag} = word
+ |> String.graphemes
+ |> Enum.map_reduce(%{}, fn c, b ->
+ {c, Map.put(b, c, Map.get(b, c, 0) + 1)}
+ end)
+ bag
+ end
+
+ def common_characters(words) do
+ common =
+ # make multisets of the words' characters
+ words |> Enum.map(fn word -> bag(word) end)
+ # find the intersection of the multisets
+ |> Enum.reduce(fn b, c ->
+ # the function returns the smallest count
+ Map.intersect(b, c, fn _k, v1, v2 -> min(v1, v2) end)
+ end)
+ # convert the map into a list of common characters
+ {_, list} = common
+ |> Map.keys
+ |> Enum.map_reduce([], fn char, list ->
+ count = Map.get(common, char)
+ {char, list ++ List.duplicate(char, count)}
+ end)
+ list
+ end
+
+ def quoted_list(words) do
+ words
+ |> Enum.map(fn w -> "\"#{w}\"" end)
+ |> Enum.join(", ")
+ end
+
+ def solution(words) do
+ IO.puts("Input: @words = (#{quoted_list(words)})")
+ common = common_characters(words)
+ IO.puts("Output: = (#{quoted_list(common)})")
+ end
+end
+
+IO.puts("Example 1:")
+PWC.solution(["bella", "label", "roller"])
+
+IO.puts("\nExample 2:")
+PWC.solution(["cool", "lock", "cook"])
+
+IO.puts("\nExample 3:")
+PWC.solution(["hello", "world", "pole"])
+
+IO.puts("\nExample 4:")
+PWC.solution(["abc", "def", "ghi"])
+
+IO.puts("\nExample 5:")
+PWC.solution(["aab", "aac", "aaa"])
diff --git a/challenge-335/packy-anderson/elixir/ch-2.exs b/challenge-335/packy-anderson/elixir/ch-2.exs
new file mode 100755
index 0000000000..4aa2a804d3
--- /dev/null
+++ b/challenge-335/packy-anderson/elixir/ch-2.exs
@@ -0,0 +1,123 @@
+#!/usr/bin/env elixir
+
+defmodule PWC do
+ def empty_game_board() do
+ [
+ [ "_", "_", "_" ],
+ [ "_", "_", "_" ],
+ [ "_", "_", "_" ]
+ ]
+ end
+
+ def display_game_board([], output), do: output
+ def display_game_board([r | board], output) do
+ display_game_board(board,
+ output <> "\n[ " <> Enum.join(r, " ") <> " ]"
+ )
+ end
+
+ def display_game_board(board) do
+ display_game_board(board, "Game Board:")
+ end
+
+ def make_move(letter, move, board) do
+ y = List.first(move)
+ x = List.last(move)
+ List.replace_at(
+ board, y,
+ List.replace_at(
+ Enum.at(board, y), x, letter
+ )
+ )
+ end
+
+ def make_moves([], _, board), do: board
+ def make_moves([move | moves], letter, board) do
+ board = make_move(letter, move, board)
+ letter = if letter == "A", do: "B", else: "A"
+ make_moves(moves, letter, board)
+ end
+
+ def same(x, y, z), do: x != "_" && x == y && y == z
+
+ def check_rows([]), do: {:error, :not_found}
+ def check_rows([row | board]) do
+ if same(Enum.at(row, 0),
+ Enum.at(row, 1),
+ Enum.at(row, 2)) do
+ {:ok, Enum.at(row, 0)} # winner
+ else
+ check_rows(board) # check next row
+ end
+ end
+
+ def at_2d(board, y, x), do: Enum.at(Enum.at(board, y), x)
+
+ def check_columns(_, x) when x > 2, do: {:error, :not_found}
+ def check_columns(board, x) do
+ if same(at_2d(board, 0, x),
+ at_2d(board, 1, x),
+ at_2d(board, 2, x)) do
+ {:ok, at_2d(board, 0, x)} # winner
+ else
+ check_columns(board, x+1) # check next column
+ end
+ end
+
+ def check_diagonals(board) do
+ cond do
+ same(at_2d(board, 0, 0),
+ at_2d(board, 1, 1),
+ at_2d(board, 2, 2)) ->
+ {:ok, at_2d(board, 1, 1)} # winner
+ same(at_2d(board, 2, 0),
+ at_2d(board, 1, 1),
+ at_2d(board, 0, 2)) ->
+ {:ok, at_2d(board, 1, 1)} # winner
+ true ->
+ {:error, :not_found}
+ end
+ end
+
+ def check_for_winner(board, moves) do
+ with {:error, :not_found} <- check_rows(board),
+ {:error, :not_found} <- check_columns(board, 0),
+ {:error, :not_found} <- check_diagonals(board) do
+ if length(moves) < 9, do: "Pending", else: "Draw"
+ else
+ {:ok, winner} -> winner
+ end
+ end
+
+ def find_winner(moves) do
+ board = make_moves(moves, "A", empty_game_board())
+ { check_for_winner(board, moves), display_game_board(board) }
+ end
+
+ def move_list(moves) do
+ moves
+ |> Enum.map(fn m -> "[#{List.first(m)},#{List.last(m)}]" end)
+ |> Enum.join(", ")
+ end
+
+ def solution(moves) do
+ IO.puts("Input: @moves = (#{move_list(moves)})")
+ {winner, board} = find_winner(moves)
+ IO.puts("Output: #{winner}\n\n#{board}")
+ end
+end
+
+IO.puts("Example 1:")
+PWC.solution([[0,0],[2,0],[1,1],[2,1],[2,2]])
+
+IO.puts("\nExample 2:")
+PWC.solution([[0,0],[1,1],[0,1],[0,2],[1,0],[2,0]])
+
+IO.puts("\nExample 3:")
+PWC.solution([[0,0],[1,1],[2,0],[1,0],[1,2],[2,1],[0,1],[0,2],[2,2]])
+
+IO.puts("\nExample 4:")
+PWC.solution([[0,0],[1,1]])
+
+IO.puts("\nExample 5:")
+PWC.solution([[1,1],[0,0],[2,2],[0,1],[1,0],[0,2]])
diff --git a/challenge-335/packy-anderson/perl/ch-1.pl b/challenge-335/packy-anderson/perl/ch-1.pl
new file mode 100755
index 0000000000..8390ca3224
--- /dev/null
+++ b/challenge-335/packy-anderson/perl/ch-1.pl
@@ -0,0 +1,36 @@
+#!/usr/bin/env perl
+use v5.40;
+
+use List::AllUtils qw( reduce );
+use Set::Bag;
+
+sub commonCharacters(@words) {
+ my @bags = map {
+ Set::Bag->new( map { $_ => 1 } split //, $_ )
+ } @words;
+ my $common = reduce { $a & $b } @bags;
+ return sort map { ($_) x $common->grab($_) } $common->elements;
+}
+
+sub solution($words) {
+ my $list = join ', ', map { qq{"$_"} } @$words;
+ say qq/Input: \@words = ($list)/;
+ my @common = commonCharacters(@$words);
+ $list = join ', ', map { qq{"$_"} } @common;
+ say qq/Output: ($list)/;
+}
+
+say "Example 1:";
+solution(["bella", "label", "roller"]);
+
+say "\nExample 2:";
+solution(["cool", "lock", "cook"]);
+
+say "\nExample 3:";
+solution(["hello", "world", "pole"]);
+
+say "\nExample 4:";
+solution(["abc", "def", "ghi"]);
+
+say "\nExample 5:";
+solution(["aab", "aac", "aaa"]);
diff --git a/challenge-335/packy-anderson/perl/ch-2.pl b/challenge-335/packy-anderson/perl/ch-2.pl
new file mode 100755
index 0000000000..47c6549b99
--- /dev/null
+++ b/challenge-335/packy-anderson/perl/ch-2.pl
@@ -0,0 +1,85 @@
+#!/usr/bin/env perl
+use v5.40;
+
+sub emptyGameBoard() {
+ return [
+ [ '_', '_', '_' ],
+ [ '_', '_', '_' ],
+ [ '_', '_', '_' ]
+ ];
+}
+
+sub displayGameBoard(@board) {
+ my $output = "Game Board:\n";
+ foreach my $row (@board) {
+ $output .= "[ " . join(' ', @$row) . " ]\n";
+ }
+ $output;
+}
+
+sub makeMove($letter, $move, $board) {
+ my ($y,$x) = ($move->[0], $move->[1]);
+ $board->[$y]->[$x] = $letter;
+}
+
+sub findWinner(@moves) {
+ my $board = emptyGameBoard();
+
+ my $letter = 'A';
+ my $movecount = scalar(@moves);
+
+ while (@moves) {
+ my $move = shift @moves;
+ makeMove($letter, $move, $board);
+ $letter = ($letter eq 'A') ? 'B' : 'A';
+ }
+
+ # check rows
+ for my $y (0..2) {
+ return($board->[$y][0], displayGameBoard(@$board))
+ if ($board->[$y][0] eq $board->[$y][1] eq $board->[$y][2])
+ && $board->[$y][0] ne '_';
+ }
+
+ # check columns
+ for my $x (0..2) {
+ return($board->[0][$x], displayGameBoard(@$board))
+ if ($board->[0][$x] eq $board->[1][$x] eq $board->[2][$x])
+ && $board->[0][$x] ne '_';
+ }
+
+ # check diagonals
+ return($board->[1][1], displayGameBoard(@$board))
+ if (($board->[0][0] eq $board->[1][1] eq $board->[2][2])
+ || ($board->[2][0] eq $board->[1][1] eq $board->[0][2]))
+ && $board->[1][1] ne '_';
+
+ # no winner
+ return(
+ $movecount < 9 ? 'Pending' : 'Draw',
+ displayGameBoard(@$board)
+ );
+}
+
+sub solution($moves) {
+ my $list = join ', ', map { '[' . join(',', @$_) . ']' } @$moves;
+ say qq/Input: \@moves = ($list)/;
+ my ($winner, $board) = findWinner(@$moves);
+ print qq/Output: $winner\n\n$board/;
+}
+
+say "Example 1:";
+solution([[0,0],[2,0],[1,1],[2,1],[2,2]]);
+
+say "\nExample 2:";
+solution([[0,0],[1,1],[0,1],[0,2],[1,0],[2,0]]);
+
+say "\nExample 3:";
+solution([[0,0],[1,1],[2,0],[1,0],[1,2],[2,1],[0,1],[0,2],[2,2]]);
+
+say "\nExample 4:";
+solution([[0,0],[1,1]]);
+
+say "\nExample 5:";
+solution([[1,1],[0,0],[2,2],[0,1],[1,0],[0,2]]);
+
diff --git a/challenge-335/packy-anderson/python/ch-1.py b/challenge-335/packy-anderson/python/ch-1.py
new file mode 100755
index 0000000000..3d5691d248
--- /dev/null
+++ b/challenge-335/packy-anderson/python/ch-1.py
@@ -0,0 +1,42 @@
+#!/usr/bin/env python
+
+from collections import Counter
+
+def common_characters(words):
+ # make multisets of the words' characters
+ bags = [ Counter(list(w)) for w in words ]
+ # make a list of sets of the keys in each bag
+ sets = [ set(b.keys()) for b in bags ]
+ # convert the keys to sets so we can find the intersection
+ keys = set.intersection(*sets)
+ common = []
+ for key in keys:
+ # get the lowest count for the key from each bag
+ lowest = min([ b[key] for b in bags ])
+ # insert that many of the key into the common array
+ for i in range(lowest): common.append(key)
+ return sorted(common)
+
+def quoted_list(arr):
+ return ', '.join([ f'"{e}"' for e in arr ])
+
+def solution(words):
+ print(f'Input: @nums = ({quoted_list(words)})')
+ common = common_characters(words)
+ print(f'Output: ({quoted_list(common)})')
+
+
+print('Example 1:')
+solution(["bella", "label", "roller"])
+
+print('\nExample 2:')
+solution(["cool", "lock", "cook"])
+
+print('\nExample 3:')
+solution(["hello", "world", "pole"])
+
+print('\nExample 4:')
+solution(["abc", "def", "ghi"])
+
+print('\nExample 5:')
+solution(["aab", "aac", "aaa"]) \ No newline at end of file
diff --git a/challenge-335/packy-anderson/python/ch-2.py b/challenge-335/packy-anderson/python/ch-2.py
new file mode 100755
index 0000000000..7b514e5ba4
--- /dev/null
+++ b/challenge-335/packy-anderson/python/ch-2.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+
+def emptyGameBoard():
+ return [
+ [ '_', '_', '_' ],
+ [ '_', '_', '_' ],
+ [ '_', '_', '_' ]
+ ]
+
+def displayGameBoard(board):
+ output = "Game Board:\n"
+ for r in board:
+ output += "[ " + " ".join(r) + " ]\n"
+ return output
+
+def makeMove(letter, move, board):
+ y,x = move[0], move[1]
+ board[y][x] = letter
+
+def find_winner(moves):
+ board = emptyGameBoard()
+
+ letter = 'A'
+ movecount = len(moves)
+ while moves:
+ move = moves.pop(0)
+ makeMove(letter, move, board)
+ letter = 'B' if letter == 'A' else 'A'
+
+ # check rows
+ for y in range(3):
+ if (board[y][0] != '_' and
+ (board[y][0] == board[y][1] == board[y][2])):
+ return board[y][0], displayGameBoard(board)
+
+ # check columns
+ for x in range(3):
+ if (board[0][x] != '_' and
+ (board[0][x] == board[1][x] == board[2][x])):
+ return board[0][x], displayGameBoard(board)
+
+ # check diagonals
+ if (board[1][1] != '_' and
+ ((board[0][0] == board[1][1] == board[2][2]) or
+ (board[2][0] == board[1][1] == board[0][2]))):
+ return board[1][1], displayGameBoard(board)
+
+ # no winner
+ return (
+ 'Pending' if movecount < 9 else 'Draw',
+ displayGameBoard(board)
+ )
+
+def solution(moves):
+ move_list = ', '.join(
+ [ '[' + ','.join([str(c) for c in r]) + ']' for r in moves ]
+ )
+ print(f'Input: @moves = ({move_list})')
+ winner, board = find_winner(moves)
+ print(f'Output: {winner}\n\n{board}')
+
+
+print('Example 1:')
+solution([[0,0],[2,0],[1,1],[2,1],[2,2]])
+
+print('\nExample 2:')
+solution([[0,0],[1,1],[0,1],[0,2],[1,0],[2,0]])
+
+print('\nExample 3:')
+solution([[0,0],[1,1],[2,0],[1,0],[1,2],[2,1],[0,1],[0,2],[2,2]])
+
+print('\nExample 4:')
+solution([[0,0],[1,1]])
+
+print('\nExample 5:')
+solution([[1,1],[0,0],[2,2],[0,1],[1,0],[0,2]])
diff --git a/challenge-335/packy-anderson/raku/ch-1.raku b/challenge-335/packy-anderson/raku/ch-1.raku
new file mode 100755
index 0000000000..0e2aff01e6
--- /dev/null
+++ b/challenge-335/packy-anderson/raku/ch-1.raku
@@ -0,0 +1,29 @@
+#!/usr/bin/env raku
+use v6;
+
+sub commonCharacters(@words) {
+ @words.map({ $_.comb.Bag }).reduce(&infix:<∩>).kxxv.sort;
+}
+
+sub solution(@words) {
+ my $list = @words.map({ qq{"$_"} }).join(', ');
+ say qq/Input: \@words = ($list)/;
+ my @common = commonCharacters(@words);
+ $list = @common.map({ qq{"$_"} }).join(', ');
+ say qq/Output: ($list)/;
+}
+
+say "Example 1:";
+solution(["bella", "label", "roller"]);
+
+say "\nExample 2:";
+solution(["cool", "lock", "cook"]);
+
+say "\nExample 3:";
+solution(["hello", "world", "pole"]);
+
+say "\nExample 4:";
+solution(["abc", "def", "ghi"]);
+
+say "\nExample 5:";
+solution(["aab", "aac", "aaa"]);
diff --git a/challenge-335/packy-anderson/raku/ch-2.raku b/challenge-335/packy-anderson/raku/ch-2.raku
new file mode 100755
index 0000000000..297f5caf78
--- /dev/null
+++ b/challenge-335/packy-anderson/raku/ch-2.raku
@@ -0,0 +1,81 @@
+#!/usr/bin/env raku
+use v6;
+
+sub emptyGameBoard() {
+ return [
+ [ '_', '_', '_' ] xx 3
+ ];
+}
+
+sub displayGameBoard(@board) {
+ my $output = "Game Board:\n";
+ for @board -> @row {
+ $output ~= '[ ' ~ @row.join(' ') ~ ' ]' ~ "\n";
+ }
+ $output;
+}
+
+sub makeMove($letter, @move, @board) {
+ my ($y,$x) = (@move[0;0], @move[0;1]);
+ @board[$y;$x] = $letter;
+}
+
+sub findWinner(@moves) {
+ my @board = emptyGameBoard();
+
+ my $letter = 'A';
+ my $movecount = @moves.elems;
+ while (@moves) {
+ my @move = @moves.shift;
+ makeMove($letter, @move, @board);
+ $letter = ($letter eq 'A') ?? 'B' !! 'A';
+ }
+
+ # check rows
+ for 0..2 -> $y {
+ return(@board[$y;0], displayGameBoard(@board))
+ if (@board[$y;0] eq @board[$y;1] eq @board[$y;2])
+ && @board[$y;0] ne '_';
+ }
+
+ # check columns
+ for 0..2 -> $x {
+ return(@board[0;$x], displayGameBoard(@board))
+ if (@board[0;$x] eq @board[1;$x] eq @board[2;$x])
+ && @board[0;$x] ne '_';
+ }
+
+ # check diagonals
+ return(@board[1;1], displayGameBoard(@board))
+ if ((@board[0;0] eq @board[1;1] eq @board[2;2])
+ || (@board[2;0] eq @board[1;1] eq @board[0;2]))
+ && @board[1;1] ne '_';
+
+ # no winner
+ return(
+ $movecount < 9 ?? 'Pending' !! 'Draw',
+ displayGameBoard(@board)
+ );
+}
+
+sub solution(@moves) {
+ my $list = @moves.map({ '[' ~ $_.join(',') ~ ']'}).join(', ');
+ say qq/Input: \@moves = ($list)/;
+ my ($winner, $board) = findWinner(@moves);
+ print qq/Output: $winner\n\n$board/;
+}
+
+say "Example 1:";
+solution([[0,0],[2,0],[1,1],[2,1],[2,2]]);
+
+say "\nExample 2:";
+solution([[0,0],[1,1],[0,1],[0,2],[1,0],[2,0]]);
+
+say "\nExample 3:";
+solution([[0,0],[1,1],[2,0],[1,0],[1,2],[2,1],[0,1],[0,2],[2,2]]);
+
+say "\nExample 4:";
+solution([[0,0],[1,1]]);
+
+say "\nExample 5:";
+solution([[1,1],[0,0],[2,2],[0,1],[1,0],[0,2]]);