diff options
| -rw-r--r-- | challenge-335/packy-anderson/README.md | 2 | ||||
| -rw-r--r-- | challenge-335/packy-anderson/blog.txt | 1 | ||||
| -rwxr-xr-x | challenge-335/packy-anderson/elixir/ch-1.exs | 58 | ||||
| -rwxr-xr-x | challenge-335/packy-anderson/elixir/ch-2.exs | 123 | ||||
| -rwxr-xr-x | challenge-335/packy-anderson/perl/ch-1.pl | 36 | ||||
| -rwxr-xr-x | challenge-335/packy-anderson/perl/ch-2.pl | 85 | ||||
| -rwxr-xr-x | challenge-335/packy-anderson/python/ch-1.py | 42 | ||||
| -rwxr-xr-x | challenge-335/packy-anderson/python/ch-2.py | 76 | ||||
| -rwxr-xr-x | challenge-335/packy-anderson/raku/ch-1.raku | 29 | ||||
| -rwxr-xr-x | challenge-335/packy-anderson/raku/ch-2.raku | 81 |
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]]); |
