aboutsummaryrefslogtreecommitdiff
path: root/challenge-276/matthias-muth/README.md
diff options
context:
space:
mode:
authorMohammad S Anwar <mohammad.anwar@yahoo.com>2024-07-07 23:19:39 +0100
committerMohammad S Anwar <mohammad.anwar@yahoo.com>2024-07-07 23:19:39 +0100
commit3e7733d98857977d4041d66e5e79a19b9fdbb655 (patch)
tree2d055af46b256c545da330533e68b16dad19fb12 /challenge-276/matthias-muth/README.md
parent40faf35f353be663006cfc792193af16056ce9fe (diff)
parent088b6d4bf7c2a5dcd9d6215844626321ab20d3cb (diff)
downloadperlweeklychallenge-club-3e7733d98857977d4041d66e5e79a19b9fdbb655.tar.gz
perlweeklychallenge-club-3e7733d98857977d4041d66e5e79a19b9fdbb655.tar.bz2
perlweeklychallenge-club-3e7733d98857977d4041d66e5e79a19b9fdbb655.zip
Merge branch 'master' of https://github.com/manwar/perlweeklychallenge-club
Diffstat (limited to 'challenge-276/matthias-muth/README.md')
-rw-r--r--challenge-276/matthias-muth/README.md205
1 files changed, 4 insertions, 201 deletions
diff --git a/challenge-276/matthias-muth/README.md b/challenge-276/matthias-muth/README.md
index 551d37babf..10e53d1eb9 100644
--- a/challenge-276/matthias-muth/README.md
+++ b/challenge-276/matthias-muth/README.md
@@ -1,202 +1,5 @@
-# Broken Keys and Test Driven Understanding (tm)
+**Challenge 276 solutions in Perl by Matthias Muth**
+<br/>
+(no blog post this time...)
-**Challenge 275 solutions in Perl by Matthias Muth**
-
-## Task 1: Broken Keys
-
-> You are given a sentence, $sentence and list of broken keys @keys.<br/>
-> Write a script to find out how many words can be typed fully.<br/>
-> <br/>
-> Example 1<br/>
-> Input: \$sentence = "Perl Weekly Challenge", @keys = ('l', 'a')<br/>
-> Output: 0<br/>
-> <br/>
-> Example 2<br/>
-> Input: \$sentence = "Perl and Raku", @keys = ('a')<br/>
-> Output: 1<br/>
-> Only Perl since the other word two words contain 'a' and can't be typed fully.<br/>
-> <br/>
-> Example 3<br/>
-> Input: \$sentence = "Well done Team PWC", @keys = ('l', 'o')<br/>
-> Output: 2<br/>
-> <br/>
-> Example 4<br/>
-> Input: \$sentence = "The joys of polyglottism", @keys = ('T')<br/>
-> Output: 2<br/>
-
-Regular expressions make this is an easy one.
-
-First thing, we have to separate the words in the sentence to deal with them one by one.<br/>
-No problem, just a standard call of `split " ", $sentence`.
-
-To find out whether a word contains a 'broken' key
-we can put those keys into a 'bracketed character class',
-and then check the word against that.
-For the second example above, we would try a match like this:
-
-```perl[]
- ! /[lo]/i
-```
-
-The `//i` modifier makes sure that lower or upper case doesn't matter
-(needed in the third example).
-
-So then let's combine the broken keys into a string that we can use in the regular expressions,
-and then use it for counting the matches.
-For the counting, `grep` in scalar context does the job.
-
-```perl
-sub broken_keys( $sentence, $keys ) {
- my $keys_as_string = join( "", $keys->@* );
- return scalar grep ! /[$keys_as_string]/i, split " ", $sentence;
-}
-```
-
-Et voilĂ !
-
-## Task 2: Replace Digits
-
-> You are given an alphanumeric string, \$str, where each character is either a letter or a digit.<br/>
-> Write a script to replace each digit in the given string with the value of the previous letter plus (digit) places.<br/>
-> <br/>
-> Example 1<br/>
-> Input: \$str = 'a1c1e1'<br/>
-> Ouput: 'abcdef'<br/>
-> shift('a', 1) => 'b'<br/>
-> shift('c', 1) => 'd'<br/>
-> shift('e', 1) => 'f'<br/>
-> <br/>
-> Example 2<br/>
-> Input: \$str = 'a1b2c3d4'<br/>
-> Output: 'abbdcfdh'<br/>
-> shift('a', 1) => 'b'<br/>
-> shift('b', 2) => 'd'<br/>
-> shift('c', 3) => 'f'<br/>
-> shift('d', 4) => 'h'<br/>
-> <br/>
-> Example 3<br/>
-> Input: \$str = 'b2b'<br/>
-> Output: 'bdb'<br/>
-> <br/>
-> Example 4<br/>
-> Input: \$str = 'a16z'<br/>
-> Output: 'abgz'<br/>
-
-This task is a bit more tricky. At least for me.<br/>
-Not tricky for the programming,
-but it took me an 'iterative approach' to understand the details of the specification.
-As simple (and complete and correct!) as it seems, I misunderstood it as being *too* simple.
-
-So this is my 'test driven understanding' approach.
-
-##### First try
-
-Maybe my first try was too naive.
-Repetitively match a letter and a digit,
-and then replace the digit by the properly shifted letter directly in the substitution.<br/>
-That means a `s///g` global substitution, and I added these additional 'tricks':
-
-* using the `[:alpha:]` POSIX character class to capture an upper or lower case letter,
-* using an `e` modifier to call a code block to determine the replacement string with the shifted letter,
-* using an `r` modifier to return the modified result instead of changing the input string,
-* using an `x` modifier for adding some spaces to improve readability:
-
-```perl
-sub replace_digits_1( $str ) {
- return $str =~ s{ ([[:alpha:]]) (\d) }{ $1 . chr( ord( $1 ) + $2 ) }egr;
-}
-```
-
-Great, that works well! ...
-Except for the fourth example!<br/>
-There we have two digits in a row (`'a16'`),
-and we didn't get the second digit.
-We need kind of an 'overlapping' operation.
-
-##### Second try.
-
-So next, the second approach,
-where I use an explicit loop, always restarting at the beginning of the string,
-and modifying the string itself:
-
-```perl
-sub replace_digits_2( $str ) {
- while ( $str =~
- s{ ([[:alpha:]]) (\d) }{ $1 . chr( ord( $1 ) + $2 ) }xe )
- {
- # Everything is in the loop condiiton.
- }
- return $str;
-}
-```
-
-Great, that's better!
-We catch the fourth example's second digit now, after replacing the first one.
-
-But the resulting letter for the second digit is off by one!
-
-My misunderstanding, again. Actually, we should not replace
-```perl
- 'a16' => ('a' shifted by 1 ) => 'ab6'
- 'b6' => ('b' shifted by 6 ) => 'bh'
-```
-but, in one operation:
-```perl
- 'a16' => ('a' shifted by 1 ) => 'ab6'
- ('a' shifted by 6 ) => 'abg'
-```
-
-##### So, third try:
-
-Same loop, but replacing sequences of digits from *right to left* instead of left to right.
-I capture the digits in between, and leave them for the next iterations,
-replacing the rightmost digit first:
-
-```perl
-sub replace_digits_3( $str ) {
- while ( $str =~
- s{ ([[:alpha:]]) (\d*) (\d) }{ "$1$2" . chr( ord( $1 ) + $3 ) }xe )
- {
- # Everything is in the loop condiiton.
- }
- return $str;
-}
-```
-
-Finally it works!
-
-Interesting that the bigger difficulty for me this time was not the programming itself,
-but to capture the task specification correctly.
-
-How good it is to have and use tests!
-
-##### 'Refacturing the understanding'
-
-I now understood that the task actually is not about replacing 'a letter and a digit',
-but more replacing 'a letter and a sequence of digits'.
-
-This lead me to yet another approach:<br/>
-Once the letter and *all following digits* are captured
-(using a `(\d+)` pattern), we build the replacement from
-
-- the letter itself,
-- the same letter, shifted by every digit's value.
-
-*Now* that sounds logical, of course! :-)
-
-I can turn back to the `s///g` style global substitution and avoid the `while` loop.
-Using `split` to split up the sequence of digits, and `map` to loop over the single digits.
-
-```perl
-sub replace_digits_4( $str ) {
- return $str =~ s{ ([[:alpha:]]) (\d+) }{
- join "", $1, map chr( ord( $1 ) + $_ ), split "", $2;
- }xegr;
-}
-```
-
-Probably this is my solution that best reflects the task's specification.
-
-What a funny experience this challenge was!
-
-#### **Thank you for the challenge!**
+**Thank you for the challenge!**