diff options
| author | Lubos Kolouch <lubos@kolouch.net> | 2025-09-16 12:25:09 +0200 |
|---|---|---|
| committer | Lubos Kolouch <lubos@kolouch.net> | 2025-09-16 12:50:05 +0200 |
| commit | a445a4de5501bcd731883b25ad138bace3417a8b (patch) | |
| tree | dffeb343fcc80a52f5d53f4b5e92609259aeec21 | |
| parent | 65fdce07ae9b197000d4c64b9f1699cef16befe8 (diff) | |
| download | perlweeklychallenge-club-a445a4de5501bcd731883b25ad138bace3417a8b.tar.gz perlweeklychallenge-club-a445a4de5501bcd731883b25ad138bace3417a8b.tar.bz2 perlweeklychallenge-club-a445a4de5501bcd731883b25ad138bace3417a8b.zip | |
Add challenge 336 solutions for Lubos
| -rw-r--r-- | challenge-336/lubos-kolouch/README | 76 | ||||
| -rw-r--r-- | challenge-336/lubos-kolouch/perl/ch-1.pl | 80 | ||||
| -rw-r--r-- | challenge-336/lubos-kolouch/perl/ch-2.pl | 83 | ||||
| -rw-r--r-- | challenge-336/lubos-kolouch/python/ch-1.py | 45 | ||||
| -rw-r--r-- | challenge-336/lubos-kolouch/python/ch-2.py | 48 |
5 files changed, 332 insertions, 0 deletions
diff --git a/challenge-336/lubos-kolouch/README b/challenge-336/lubos-kolouch/README index 921b2d9f4a..a8bfeee6c2 100644 --- a/challenge-336/lubos-kolouch/README +++ b/challenge-336/lubos-kolouch/README @@ -1 +1,77 @@ Solutions by Lubos Kolouch. + +# The Weekly Challenge - 336 + +## Task 1: Equal Group + +### Description + +Given an array of integers, determine whether it can be partitioned into one or +more groups of equal size (at least two elements per group) such that every +member within a group has the same value. + +### Solution + +#### Perl (ch-1.pl) + +Counts occurrences of each value, ensures every frequency is at least two, and +computes the greatest common divisor across the frequencies. A GCD of two or +more confirms that the array can be divided into uniform groups. Embedded +`Test::More` cases cover the official examples. + +#### Python (ch-1.py) + +Uses `collections.Counter` and `math.gcd` to mirror the Perl logic. Type hints +and `unittest` tests verify the five examples supplied in the challenge. + +### Examples + +- Example 1: `[1, 1, 2, 2, 2, 2]` → `True` +- Example 2: `[1, 1, 1, 2, 2, 2, 3, 3]` → `False` +- Example 3: `[5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7]` → `True` +- Example 4: `[1, 2, 3, 4]` → `False` +- Example 5: `[8, 8, 9, 9, 10, 10, 11, 11]` → `True` + +## Task 2: Final Score + +### Description + +Given a sequence of scoring operations consisting of integers, `C`, `D`, and +`+`, compute the final total. `C` removes the previous score, `D` doubles it, +and `+` adds the last two scores. + +### Solution + +#### Perl (ch-2.pl) + +Maintains a stack of recorded scores, applying each operation as specified, and +returns the sum of the stack. `Test::More` subtests cover the challenge cases. + +#### Python (ch-2.py) + +Implements the same stack-based logic using type annotations and `unittest` +coverage for the provided examples. + +### Examples + +- Example 1: `["5", "2", "C", "D", "+"]` → `30` +- Example 2: `["5", "-2", "4", "C", "D", "9", "+", "+"]` → `27` +- Example 3: `["7", "D", "D", "C", "+", "3"]` → `45` +- Example 4: `["-5", "-10", "+", "D", "C", "+"]` → `-55` +- Example 5: `["3", "6", "+", "D", "C", "8", "+", "D", "-2", "C", "+"]` → `128` + +## Running the Code + +### Perl + +```bash +perl ch-1.pl +perl ch-2.pl +``` + +### Python + +```bash +python3 ch-1.py +python3 ch-2.py +``` diff --git a/challenge-336/lubos-kolouch/perl/ch-1.pl b/challenge-336/lubos-kolouch/perl/ch-1.pl new file mode 100644 index 0000000000..3a4a7d6f10 --- /dev/null +++ b/challenge-336/lubos-kolouch/perl/ch-1.pl @@ -0,0 +1,80 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +=head1 NAME + +ch-1.pl - The Weekly Challenge 336 Task 1: Equal Group + +=head1 DESCRIPTION + +Determine whether an array of integers can be partitioned into one or more +groups so that: + +=over 4 + +=item * all groups have the same size (at least two members), and + +=item * all values inside each group are identical. + +=back + +The implementation counts occurrences of each value and verifies that the +greatest common divisor of the counts is at least two. + +=head1 AUTHOR + +Lubos Kolouch + +=cut + +use List::Util qw(all reduce); +use Test::More tests => 5; + +use constant IntArray => 'ARRAY'; + +sub _gcd { + my ( $a, $b ) = @_; + ( $a, $b ) = ( abs $a, abs $b ); + return $a if $b == 0; + return _gcd( $b, $a % $b ); +} + +sub equal_group { + my (@ints) = @_; + return 0 if @ints < 2; + + my %freq; + $freq{$_}++ for @ints; + my @counts = values %freq; + + return 0 if !all { $_ >= 2 } @counts; + + my $gcd = reduce { _gcd( $a, $b ) } @counts; + return $gcd >= 2 ? 1 : 0; +} + +subtest 'Example 1' => sub { + my @ints = ( 1, 1, 2, 2, 2, 2 ); + ok( equal_group(@ints), 'Groups (1,1), (2,2), (2,2)' ); +}; + +subtest 'Example 2' => sub { + my @ints = ( 1, 1, 1, 2, 2, 2, 3, 3 ); + ok( !equal_group(@ints), 'Cannot group equally' ); +}; + +subtest 'Example 3' => sub { + my @ints = ( 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7 ); + ok( equal_group(@ints), 'Groups of size 6' ); +}; + +subtest 'Example 4' => sub { + my @ints = ( 1, 2, 3, 4 ); + ok( !equal_group(@ints), 'Distinct values cannot group' ); +}; + +subtest 'Example 5' => sub { + my @ints = ( 8, 8, 9, 9, 10, 10, 11, 11 ); + ok( equal_group(@ints), 'Pairs of equal values' ); +}; diff --git a/challenge-336/lubos-kolouch/perl/ch-2.pl b/challenge-336/lubos-kolouch/perl/ch-2.pl new file mode 100644 index 0000000000..8aceb3b007 --- /dev/null +++ b/challenge-336/lubos-kolouch/perl/ch-2.pl @@ -0,0 +1,83 @@ +#!/usr/bin/env perl +use strict; +use warnings; + +=head1 NAME + +ch-2.pl - The Weekly Challenge 336 Task 2: Final Score + +=head1 DESCRIPTION + +Compute the total score for a sequence of operations. Each entry is one of: + +=over 4 + +=item * an integer representing a new score, + +=item * C<'C'> to invalidate and remove the previous score, + +=item * C<'D'> to record double the previous score, or + +=item * C<'+'> to add the sum of the previous two scores. + +=back + +The solution tracks scores on a stack and sums the remaining values. + +=head1 AUTHOR + +Lubos Kolouch + +=cut + +use List::Util qw(sum0); +use Test::More tests => 5; + +use constant ScoreList => 'ARRAY'; + +sub final_score { + my (@entries) = @_; + my @record; + + for my $entry (@entries) { + if ( $entry eq 'C' ) { + pop @record; + } + elsif ( $entry eq 'D' ) { + push @record, 2 * $record[-1]; + } + elsif ( $entry eq '+' ) { + push @record, $record[-1] + $record[-2]; + } + else { + push @record, 0 + $entry; + } + } + + return sum0(@record); +} + +subtest 'Example 1' => sub { + my @scores = qw(5 2 C D +); + is( final_score(@scores), 30, 'Total score 30' ); +}; + +subtest 'Example 2' => sub { + my @scores = qw(5 -2 4 C D 9 + +); + is( final_score(@scores), 27, 'Total score 27' ); +}; + +subtest 'Example 3' => sub { + my @scores = qw(7 D D C + 3); + is( final_score(@scores), 45, 'Total score 45' ); +}; + +subtest 'Example 4' => sub { + my @scores = qw(-5 -10 + D C +); + is( final_score(@scores), -55, 'Total score -55' ); +}; + +subtest 'Example 5' => sub { + my @scores = qw(3 6 + D C 8 + D -2 C +); + is( final_score(@scores), 128, 'Total score 128' ); +}; diff --git a/challenge-336/lubos-kolouch/python/ch-1.py b/challenge-336/lubos-kolouch/python/ch-1.py new file mode 100644 index 0000000000..2643543a6d --- /dev/null +++ b/challenge-336/lubos-kolouch/python/ch-1.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +"""The Weekly Challenge 336 Task 1: Equal Group.""" +from collections import Counter +from math import gcd +import unittest + +IntList = list[int] + + +def equal_group(ints: IntList) -> bool: + """Return True if values can be partitioned into equal homogeneous groups.""" + if len(ints) < 2: + return False + + counts = Counter(ints) + if any(count < 2 for count in counts.values()): + return False + + group_size = 0 + for count in counts.values(): + group_size = gcd(group_size, count) + return group_size >= 2 + + +class TestEqualGroup(unittest.TestCase): + """Unit tests using the provided examples.""" + + def test_example1(self) -> None: + self.assertTrue(equal_group([1, 1, 2, 2, 2, 2])) + + def test_example2(self) -> None: + self.assertFalse(equal_group([1, 1, 1, 2, 2, 2, 3, 3])) + + def test_example3(self) -> None: + self.assertTrue(equal_group([5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7])) + + def test_example4(self) -> None: + self.assertFalse(equal_group([1, 2, 3, 4])) + + def test_example5(self) -> None: + self.assertTrue(equal_group([8, 8, 9, 9, 10, 10, 11, 11])) + + +if __name__ == "__main__": + unittest.main() diff --git a/challenge-336/lubos-kolouch/python/ch-2.py b/challenge-336/lubos-kolouch/python/ch-2.py new file mode 100644 index 0000000000..a7dc021f95 --- /dev/null +++ b/challenge-336/lubos-kolouch/python/ch-2.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +"""The Weekly Challenge 336 Task 2: Final Score.""" +import unittest + +ScoreList = list[str] + + +def final_score(scores: ScoreList) -> int: + """Calculate the total score from a list of operations.""" + record: list[int] = [] + for entry in scores: + if entry == "C": + record.pop() + elif entry == "D": + record.append(2 * record[-1]) + elif entry == "+": + record.append(record[-1] + record[-2]) + else: + record.append(int(entry)) + return sum(record) + + +class TestFinalScore(unittest.TestCase): + """Unit tests derived from the specification examples.""" + + def test_example1(self) -> None: + self.assertEqual(final_score(["5", "2", "C", "D", "+"]), 30) + + def test_example2(self) -> None: + self.assertEqual( + final_score(["5", "-2", "4", "C", "D", "9", "+", "+"]), 27) + + def test_example3(self) -> None: + self.assertEqual(final_score(["7", "D", "D", "C", "+", "3"]), 45) + + def test_example4(self) -> None: + self.assertEqual(final_score(["-5", "-10", "+", "D", "C", "+"]), -55) + + def test_example5(self) -> None: + self.assertEqual( + final_score( + ["3", "6", "+", "D", "C", "8", "+", "D", "-2", "C", "+"]), + 128, + ) + + +if __name__ == "__main__": + unittest.main() |
