diff options
| author | Lubos Kolouch <lubos@kolouch.net> | 2025-09-29 10:12:57 +0200 |
|---|---|---|
| committer | Lubos Kolouch <lubos@kolouch.net> | 2025-09-29 10:12:57 +0200 |
| commit | 6de3b70cb299a4ebd1e41f51194937650cf0b057 (patch) | |
| tree | dd1f62924386cffd23306707b452989f20f5e5f2 | |
| parent | dd9dab4686fc230480c1ba07dc81492311c1d41f (diff) | |
| download | perlweeklychallenge-club-6de3b70cb299a4ebd1e41f51194937650cf0b057.tar.gz perlweeklychallenge-club-6de3b70cb299a4ebd1e41f51194937650cf0b057.tar.bz2 perlweeklychallenge-club-6de3b70cb299a4ebd1e41f51194937650cf0b057.zip | |
Solve Perl Weekly Challenge: Broken Keyboard and Reverse Prefix
Implement solutions for Task 1 (Broken Keyboard) and Task 2 (Reverse
Prefix) in both Perl and Python.
| -rw-r--r-- | challenge-341/lubos-kolouch/README | 90 | ||||
| -rw-r--r-- | challenge-341/lubos-kolouch/perl/ch-1.pl | 45 | ||||
| -rw-r--r-- | challenge-341/lubos-kolouch/perl/ch-2.pl | 34 | ||||
| -rw-r--r-- | challenge-341/lubos-kolouch/python/ch-1.py | 70 | ||||
| -rw-r--r-- | challenge-341/lubos-kolouch/python/ch-2.py | 62 |
5 files changed, 233 insertions, 68 deletions
diff --git a/challenge-341/lubos-kolouch/README b/challenge-341/lubos-kolouch/README index 7035227f5b..2e275f9d57 100644 --- a/challenge-341/lubos-kolouch/README +++ b/challenge-341/lubos-kolouch/README @@ -1,79 +1,33 @@ -Solutions by Lubos Kolouch. +# Perl Weekly Challenge: Broken Keyboard and Reverse Prefix -# The Weekly Challenge - 339 - -## Task 1: Max Diff +## Task 1: Broken Keyboard ### Description - -Given an array of at least four integers, find two disjoint pairs whose product -difference is as large as possible. The difference for pairs (a, b) and (c, d) -is `(a * b) - (c * d)`, and we are interested in the maximum absolute value of -this difference across all pair selections. +Given a string containing English letters and a list of broken keys, return the count of words that can be typed completely without using any broken keys. The check is case-insensitive. ### Solution +- **Perl (ch-1.pl)**: The `broken_keyboard` function splits the input string into words and checks each word against a hash of broken keys. If a word contains no broken keys, it increments a counter. The function uses `split` for word separation and a hash for O(1) key lookup. +- **Python (ch-1.py)**: The `broken_keyboard` function uses a set for broken keys lookup, splits the string into words, and counts words that don't contain any broken keys. It uses `str.split()` and a set for efficient lookup. -#### Perl (ch-1.pl) - -Enumerates every combination of four numbers, evaluates the three possible -pairings, and keeps the maximum absolute difference between the resulting -products. Input validation ensures the list has at least four elements, with -unit tests covering the provided examples. - -#### Python (ch-1.py) - -Uses `itertools.combinations` to iterate through all quadruples of integers and -checks the three pairings of each quadruple. Tracks the maximum absolute -product difference. Type hints and `unittest` cases cover the supplied -scenarios. +### Test Cases +1. Input: "Hello World", ['d'] → Output: 1 +2. Input: "apple banana cherry", ['a', 'e'] → Output: 0 +3. Input: "Coding is fun", [] → Output: 3 +4. Input: "The Weekly Challenge", ['a', 'b'] → Output: 2 +5. Input: "Perl and Python", ['p'] → Output: 1 -### Examples - -- Example 1: `[5, 9, 3, 4, 6]` → `42` -- Example 2: `[1, -2, 3, -4]` → `10` -- Example 3: `[-3, -1, -2, -4]` → `10` -- Example 4: `[10, 2, 0, 5, 1]` → `50` -- Example 5: `[7, 8, 9, 10, 10]` → `44` - -## Task 2: Peak Point +## Task 2: Reverse Prefix ### Description - -Given a list of altitude gains, starting from altitude zero compute the running -sum and report the highest altitude reached at any step. +Given a string and a character, reverse the prefix of the string up to and including the first occurrence of the character, and return the new string. If the character is not found, return the original string. ### Solution - -#### Perl (ch-2.pl) - -Processes the gains sequentially, maintaining the cumulative altitude and the -highest value encountered. Embedded tests verify the challenge examples. - -#### Python (ch-2.py) - -Updates the running altitude for each gain and retains the maximum altitude -seen. Includes type annotations and unit tests mirroring the provided cases. - -### Examples - -- Example 1: `[-5, 1, 5, -9, 2]` → `1` -- Example 2: `[10, 10, 10, -25]` → `30` -- Example 3: `[3, -4, 2, 5, -6, 1]` → `6` -- Example 4: `[-1, -2, -3, -4]` → `0` -- Example 5: `[-10, 15, 5]` → `10` - -## Running the Code - -### Perl - -```bash -perl ch-1.pl -perl ch-2.pl -``` - -### Python - -```bash -python3 ch-1.py -python3 ch-2.py -``` +- **Perl (ch-2.pl)**: The `reverse_prefix` function uses `index` to find the character's position, extracts the prefix with `substr`, reverses it, and appends the remaining string. +- **Python (ch-2.py)**: The `reverse_prefix` function uses `str.find` to locate the character, slices the prefix, reverses it using slice notation `[::-1]`, and concatenates the rest of the string. + +### Test Cases +1. Input: "programming", "g" → Output: "gorpramming" +2. Input: "hello", "h" → Output: "hello" +3. Input: "abcdefghij", "h" → Output: "hgfedcbaij" +4. Input: "reverse", "s" → Output: "srevere" +5. Input: "perl", "r" → Output: "repl" diff --git a/challenge-341/lubos-kolouch/perl/ch-1.pl b/challenge-341/lubos-kolouch/perl/ch-1.pl new file mode 100644 index 0000000000..a241d752c2 --- /dev/null +++ b/challenge-341/lubos-kolouch/perl/ch-1.pl @@ -0,0 +1,45 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use v5.10; + +# Module docstring +# Task 1: Broken Keyboard +# Given a string and a list of broken keys, returns the count of words that can be typed completely. + +sub broken_keyboard { + my ( $str, @broken_keys ) = @_; + + # Convert broken keys to a hash for O(1) lookup + my %broken = map { $_ => 1 } @broken_keys; + + # Split string into words + my @words = split /\s+/, $str; + my $count = 0; + + # Check each word + foreach my $word (@words) { + my $can_type = 1; + + # Check if word contains any broken key + foreach my $char ( split //, lc($word) ) { + if ( exists $broken{$char} ) { + $can_type = 0; + last; + } + } + $count++ if $can_type; + } + + return $count; +} + +# Unit tests +use Test::More tests => 5; + +is( broken_keyboard( 'Hello World', 'd' ), 1, 'Example 1: Hello World, d broken' ); +is( broken_keyboard( 'apple banana cherry', 'a', 'e' ), 0, 'Example 2: apple banana cherry, a,e broken' ); +is( broken_keyboard( 'Coding is fun', () ), 3, 'Example 3: Coding is fun, no broken keys' ); +is( broken_keyboard( 'The Weekly Challenge', 'a', 'b' ), 2, 'Example 4: The Weekly Challenge, a,b broken' ); +is( broken_keyboard( 'Perl and Python', 'p' ), 1, 'Example 5: Perl and Python, p broken' ); diff --git a/challenge-341/lubos-kolouch/perl/ch-2.pl b/challenge-341/lubos-kolouch/perl/ch-2.pl new file mode 100644 index 0000000000..a4f52e6cbe --- /dev/null +++ b/challenge-341/lubos-kolouch/perl/ch-2.pl @@ -0,0 +1,34 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +use v5.10; + +# Module docstring +# Task 2: Reverse Prefix +# Given a string and a character, reverses the prefix up to the first occurrence of the character. + +sub reverse_prefix { + my ( $str, $char ) = @_; + + # Find position of first occurrence of char + my $pos = index( $str, $char ); + + # If char not found, return original string + return $str if $pos == -1; + + # Get prefix up to and including char + my $prefix = substr( $str, 0, $pos + 1 ); + + # Reverse prefix and append rest of string + return reverse($prefix) . substr( $str, $pos + 1 ); +} + +# Unit tests +use Test::More tests => 5; + +is( reverse_prefix( 'programming', 'g' ), 'gorpramming', 'Example 1: programming, g' ); +is( reverse_prefix( 'hello', 'h' ), 'hello', 'Example 2: hello, h' ); +is( reverse_prefix( 'abcdefghij', 'h' ), 'hgfedcbaij', 'Example 3: abcdefghij, h' ); +is( reverse_prefix( 'reverse', 's' ), 'srevere', 'Example 4: reverse, s' ); +is( reverse_prefix( 'perl', 'r' ), 'repl', 'Example 5: perl, r' ); diff --git a/challenge-341/lubos-kolouch/python/ch-1.py b/challenge-341/lubos-kolouch/python/ch-1.py new file mode 100644 index 0000000000..6c28d3106d --- /dev/null +++ b/challenge-341/lubos-kolouch/python/ch-1.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +""" +Task 1: Broken Keyboard +Given a string and a list of broken keys, returns the count of words that can be typed completely. +""" + +import unittest + + +def broken_keyboard(str_input: str, broken_keys: list[str]) -> int: + """ + Count words that can be typed with broken keys. + + Args: + str_input: Input string containing words + broken_keys: List of broken key characters + + Returns: + Number of words that can be typed completely + """ + # Convert broken keys to set for O(1) lookup + broken_set = set(broken_keys) + + # Split string into words + words = str_input.split() + count = 0 + + # Check each word + for word in words: + can_type = True + # Check if word contains any broken key + for char in word.lower(): + if char in broken_set: + can_type = False + break + if can_type: + count += 1 + + return count + + +# Unit tests + + +class TestBrokenKeyboard(unittest.TestCase): + + def test_example1(self): + """Test Example 1: Hello World, d broken""" + self.assertEqual(broken_keyboard("Hello World", ["d"]), 1) + + def test_example2(self): + """Test Example 2: apple banana cherry, a,e broken""" + self.assertEqual(broken_keyboard("apple banana cherry", ["a", "e"]), 0) + + def test_example3(self): + """Test Example 3: Coding is fun, no broken keys""" + self.assertEqual(broken_keyboard("Coding is fun", []), 3) + + def test_example4(self): + """Test Example 4: The Weekly Challenge, a,b broken""" + self.assertEqual(broken_keyboard("The Weekly Challenge", ["a", "b"]), + 2) + + def test_example5(self): + """Test Example 5: Perl and Python, p broken""" + self.assertEqual(broken_keyboard("Perl and Python", ["p"]), 1) + + +if __name__ == "__main__": + unittest.main() diff --git a/challenge-341/lubos-kolouch/python/ch-2.py b/challenge-341/lubos-kolouch/python/ch-2.py new file mode 100644 index 0000000000..5a6e46156e --- /dev/null +++ b/challenge-341/lubos-kolouch/python/ch-2.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +""" +Task 2: Reverse Prefix +Given a string and a character, reverses the prefix up to the first occurrence of the character. +""" + +import unittest + + +def reverse_prefix(str_input: str, char: str) -> str: + """ + Reverse prefix up to first occurrence of given character. + + Args: + str_input: Input string + char: Character to find + + Returns: + String with prefix reversed up to first occurrence of char + """ + # Find position of first occurrence of char + pos = str_input.find(char) + + # If char not found, return original string + if pos == -1: + return str_input + + # Get prefix up to and including char + prefix = str_input[:pos + 1] + + # Reverse prefix and append rest of string + return prefix[::-1] + str_input[pos + 1:] + + +# Unit tests + + +class TestReversePrefix(unittest.TestCase): + + def test_example1(self): + """Test Example 1: programming, g""" + self.assertEqual(reverse_prefix("programming", "g"), "gorpramming") + + def test_example2(self): + """Test Example 2: hello, h""" + self.assertEqual(reverse_prefix("hello", "h"), "hello") + + def test_example3(self): + """Test Example 3: abcdefghij, h""" + self.assertEqual(reverse_prefix("abcdefghij", "h"), "hgfedcbaij") + + def test_example4(self): + """Test Example 4: reverse, s""" + self.assertEqual(reverse_prefix("reverse", "s"), "srevere") + + def test_example5(self): + """Test Example 5: perl, r""" + self.assertEqual(reverse_prefix("perl", "r"), "repl") + + +if __name__ == "__main__": + unittest.main() |
