diff options
| author | Simon Green <mail@simon.green> | 2025-08-23 15:27:04 +1000 |
|---|---|---|
| committer | Simon Green <mail@simon.green> | 2025-08-23 15:27:04 +1000 |
| commit | 5fded4c63588ee61d55e38c0698abc6bd8a20e4a (patch) | |
| tree | 3ef28d4fb8ebc04cdcd56f18c8ee41b54de6bc58 | |
| parent | 4f766edf1327ad3628c824c3c00f1c1f10c50b38 (diff) | |
| download | perlweeklychallenge-club-5fded4c63588ee61d55e38c0698abc6bd8a20e4a.tar.gz perlweeklychallenge-club-5fded4c63588ee61d55e38c0698abc6bd8a20e4a.tar.bz2 perlweeklychallenge-club-5fded4c63588ee61d55e38c0698abc6bd8a20e4a.zip | |
sgreen solutions to challenge 335
| -rw-r--r-- | challenge-335/sgreen/README.md | 4 | ||||
| -rw-r--r-- | challenge-335/sgreen/blog.txt | 1 | ||||
| -rwxr-xr-x | challenge-335/sgreen/perl/ch-1.pl | 35 | ||||
| -rwxr-xr-x | challenge-335/sgreen/perl/ch-2.pl | 84 | ||||
| -rwxr-xr-x | challenge-335/sgreen/python/ch-1.py | 37 | ||||
| -rwxr-xr-x | challenge-335/sgreen/python/ch-2.py | 71 | ||||
| -rwxr-xr-x | challenge-335/sgreen/python/test.py | 30 |
7 files changed, 260 insertions, 2 deletions
diff --git a/challenge-335/sgreen/README.md b/challenge-335/sgreen/README.md index c346b56b6b..261fc0ba68 100644 --- a/challenge-335/sgreen/README.md +++ b/challenge-335/sgreen/README.md @@ -1,3 +1,3 @@ -# The Weekly Challenge 334 +# The Weekly Challenge 335 -Blog: [Perl has classes now 👍](https://dev.to/simongreennet/weekly-challenge-perl-has-classes-now-4n8e) +Blog: [The Common Winner](https://dev.to/simongreennet/weekly-challenge-the-common-winner-57ka) diff --git a/challenge-335/sgreen/blog.txt b/challenge-335/sgreen/blog.txt new file mode 100644 index 0000000000..b6adb47a7f --- /dev/null +++ b/challenge-335/sgreen/blog.txt @@ -0,0 +1 @@ +https://dev.to/simongreennet/weekly-challenge-the-common-winner-57ka
\ No newline at end of file diff --git a/challenge-335/sgreen/perl/ch-1.pl b/challenge-335/sgreen/perl/ch-1.pl new file mode 100755 index 0000000000..222a385977 --- /dev/null +++ b/challenge-335/sgreen/perl/ch-1.pl @@ -0,0 +1,35 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use feature 'say'; +use experimental 'signatures'; + +use List::Util 'min'; + +sub main (@word_array) { + my @freq_array = (); + my @solution = (); + + # Turn the words into a frequency dict + foreach my $word (@word_array) { + my %freq = (); + foreach my $letter ( split //, $word ) { + $freq{$letter}++; + } + push @freq_array, \%freq; + } + + # Find the minimum frequency of each character across all words + foreach my $letter ( sort keys %{ $freq_array[0] } ) { + my $min_freq = min( map { $_->{$letter} // 0 } @freq_array ); + if ( $min_freq > 0 ) { + # If the minimum frequency is greater than zero, add it to the solution + push @solution, ($letter) x $min_freq; + } + } + + say '(' . join( ', ', map { "\"$_\"" } @solution ) . ')'; +} + +main(@ARGV); diff --git a/challenge-335/sgreen/perl/ch-2.pl b/challenge-335/sgreen/perl/ch-2.pl new file mode 100755 index 0000000000..a37e5d5c99 --- /dev/null +++ b/challenge-335/sgreen/perl/ch-2.pl @@ -0,0 +1,84 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use feature 'say'; +use experimental 'signatures'; + +sub check_winner ($board_ref) { + my @board = @$board_ref; + + # use Data::Dumper; say Dumper(\@board); # Debugging line + # Check rows and columns + foreach my $i ( 0 .. 2 ) { + if ( $board[$i][0] eq $board[$i][1] eq $board[$i][2] ne '_' ) { + return $board[$i][0]; + } + if ( $board[0][$i] eq $board[1][$i] eq $board[2][$i] ne '_' ) { + return $board[0][$i]; + } + } + + # Check diagonals + if ( $board[0][0] eq $board[1][1] eq $board[2][2] ne '_' ) { + return $board[0][0]; + } + if ( $board[2][0] eq $board[1][1] eq $board[0][2] ne '_' ) { + return $board[2][0]; + } + + return undef; +} + +sub main (@ints) { + # Turn the input into pairs of moves + my @moves = (); + for ( my $i = 0 ; $i < $#ints ; $i += 2 ) { + push @moves, [ $ints[$i], $ints[ $i + 1 ] ]; + } + + # Initialize the board + my @board = ( [ '_', '_', '_' ], [ '_', '_', '_' ], [ '_', '_', '_' ], ); + + # Player A starts first + my $current_player = 'A'; + + foreach my $move (@moves) { + # Check the move is on the board and not already taken + if ( $move->[0] < 0 + or $move->[0] > 2 + or $move->[1] < 0 + or $move->[1] > 2 ) + { + die "Invalid move (out of bounds)\n"; + } + if ( $board[ $move->[0] ][ $move->[1] ] ne '_' ) { + die "Invalid move (already taken)\n"; + } + + # Place the move on the board + $board[ $move->[0] ][ $move->[1] ] = $current_player; + + # Check for a win + my $result = check_winner( \@board ); + if ($result) { + say $result; + return; + } + + # Switch players + $current_player = $current_player eq 'A' ? 'B' : 'A'; + } + + # We've made all moves, check for pending or draw + foreach my $row (@board) { + if ( grep { $_ eq '_' } @$row ) { + say 'Pending'; + return; + } + } + + say 'Draw'; +} + +main(@ARGV); diff --git a/challenge-335/sgreen/python/ch-1.py b/challenge-335/sgreen/python/ch-1.py new file mode 100755 index 0000000000..48a7ce776a --- /dev/null +++ b/challenge-335/sgreen/python/ch-1.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import sys +from collections import Counter + + +def common_characters(word_list: list[str]) -> list[str]: + """Find common characters in all words. + + Args: + word_list (list[str]): List of words to compare. + + Returns: + list[str]: List of common characters sorted alphabetically. + """ + solution = [] + + # Turn the words into a frequency dict + freq_list = [Counter(word) for word in word_list] + + # Find the minimum frequency of each character across all words + for letter in sorted(freq_list[0]): + min_freq = min(freq[letter] for freq in freq_list) + if min_freq > 0: + # ... and add it to the solution + solution.extend(letter * min_freq) + + return solution + + +def main(): + result = common_characters(sys.argv[1:]) + print(result) + + +if __name__ == '__main__': + main() diff --git a/challenge-335/sgreen/python/ch-2.py b/challenge-335/sgreen/python/ch-2.py new file mode 100755 index 0000000000..bf9b286364 --- /dev/null +++ b/challenge-335/sgreen/python/ch-2.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +import sys + + +def check_winner(board: list[list[str]]) -> str | None: + """ + Check the current state of the Tic Tac Toe board for a winner. + + Args: + board (list[list[str]]): The current state of the Tic Tac Toe board + + Returns: + str | None: 'A' if player A wins, 'B' if player B wins, or None if no winner yet + """ + # Check rows and columns + for i in range(3): + if board[i][0] == board[i][1] == board[i][2] != '_': + return board[i][0] + if board[0][i] == board[1][i] == board[2][i] != '_': + return board[0][i] + + # Check diagonals + if board[0][0] == board[1][1] == board[2][2] != '_': + return board[0][0] + if board[0][2] == board[1][1] == board[2][0] != '_': + return board[0][2] + + return None + + +def find_winner(moves: list[list[int]]) -> str: + # Initialize the board + board = [['_' for _ in range(3)] for _ in range(3)] + + # Player A starts first + current_player = 'A' + + for move in moves: + # Check the move is on the board and not already taken + if not 0 <= move[0] <= 2 and not 0 <= move[1] <= 2: + return "Invalid move (out of bounds)" + if board[move[0]][move[1]] != '_': + return "Invalid move (already taken)" + + # Place the move on the board + board[move[0]][move[1]] = current_player + + # Check for a win + result = check_winner(board) + if result: + return result + + # Switch players + current_player = 'B' if current_player == 'A' else 'A' + + # We've made all moves, check for pending or draw + return "Pending" if any('_' in row for row in board) else "Draw" + + +def main(): + # Convert input into integers, and pair them up + array = [int(n) for n in sys.argv[1:]] + moves = [array[i:i + 2] for i in range(0, len(array), 2)] + + result = find_winner(moves) + print(result) + + +if __name__ == '__main__': + main() diff --git a/challenge-335/sgreen/python/test.py b/challenge-335/sgreen/python/test.py new file mode 100755 index 0000000000..2f4a95cbef --- /dev/null +++ b/challenge-335/sgreen/python/test.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 + +import unittest +ch_1 = __import__('ch-1') +ch_2 = __import__('ch-2') + + +class TestClass(unittest.TestCase): + def test_ch_1(self): + self.assertEqual(ch_1.common_characters(["bella", "label", "roller"]), ["e", "l", "l"]) + self.assertEqual(ch_1.common_characters(["cool", "lock", "cook"]), ["c", "o"]) + self.assertEqual(ch_1.common_characters(["hello", "world", "pole"]), ["l", "o"]) + self.assertEqual(ch_1.common_characters(["abc", "def", "ghi"]), []) + self.assertEqual(ch_1.common_characters(["aab", "aac", "aaa"]), ["a", "a"]) + + def test_ch_2(self): + moves_1 = [[0,0],[2,0],[1,1],[2,1],[2,2]] + moves_2 = [[0,0],[1,1],[0,1],[0,2],[1,0],[2,0]] + moves_3 = [[0,0],[1,1],[2,0],[1,0],[1,2],[2,1],[0,1],[0,2],[2,2]] + moves_4 = [[0,0],[1,1]] + moves_5 = [[1,1],[0,0],[2,2],[0,1],[1,0],[0,2]] + self.assertEqual(ch_2.find_winner(moves_1), "A") + self.assertEqual(ch_2.find_winner(moves_2), "B") + self.assertEqual(ch_2.find_winner(moves_3), "Draw") + self.assertEqual(ch_2.find_winner(moves_4), "Pending") + self.assertEqual(ch_2.find_winner(moves_5), "B") + + +if __name__ == '__main__': + unittest.main() |
