# There Is Always a Regular Expression To Solve It
**Challenge 313 solutions in Perl by Matthias Muth**
This week, both my solutions use regular expressions to solve the task, resulting in concise solutions.
## Task 1: Broken Keys
> You have a broken keyboard which sometimes type a character more than once.
> You are given a string and actual typed string.
> Write a script to find out if the actual typed string is meant for the given string.
>
> **Example 1**
>
> ```text
> Input: $name = "perl", $typed = "perrrl"
> Output: true
>
> Here "r" is pressed 3 times instead of 1 time.
> ```
>
> **Example 2**
>
> ```text
> Input: $name = "raku", $typed = "rrakuuuu"
> Output: true
> ```
>
> **Example 3**
>
> ```text
> Input: $name = "python", $typed = "perl"
> Output: false
> ```
>
> **Example 4**
>
> ```text
> Input: $name = "coffeescript", $typed = "cofffeescccript"
> Output: true
> ```
For any typed string to correspond to the given string, every letter has to appear at least once, but possibly several times. We can express that with a regular expression.
As an example, if the word is `'perl'`,
then any word typed with the broken keys will be matched by this regular expression:
```perl
/^p+e+r+l+$/
```
So let's generate the regular expression from our given word:
We split the word into its characters, add a `+` sign to each of them, and then assemble everything to form the regular expression.
```perl
my $pattern = join "", map "$_+", split "", $name;
```
We then can return the result of the pattern match:
```perl
return $typed =~ /^$pattern$/;
```
And that's all:
```perl
use v5.36;
sub broken_keys( $name, $typed ) {
my $pattern = join "", map "$_+", split "", $name;
return $typed =~ /^$pattern$/;
}
```
## Task 2: Reverse Letters
> You are given a string.
> Write a script to reverse only the alphabetic characters in the string.
>
> **Example 1**
>
> ```text
> Input: $str = "p-er?l"
> Output: "l-re?p"
> ```
>
> **Example 2**
>
> ```text
> Input: $str = "wee-k!L-y"
> Output: "yLk-e!e-w"
> ```
>
> **Example 3**
>
> ```text
> Input: $str = "_c-!h_all-en!g_e"
> Output: "_e-!g_nel-la!h_c"
> ```
For this task, my strategy is to
- extract all letters,
- reverse them,
- replace each letter in the original string by the letter with the same index in the reversed string.
For extracting the letters, a regular expression with a `/g` *global* flag can be used. The reversed letters then are stored in an array:
```Perl
my @reversed_letters = reverse $str =~ /[[:alpha:]]/g;
```
For the result, all letters in the original string are replaced by their reversed counterpart. Here, a regex substitution is used, with the `/g` *global* flag, and the `/r` flag, which *returns* the modified string. A variable `$index` is used to select the matching letter from the reversed letters, being incremented after each substitution.
```perl
my $index = 0;
return $str =~ s/[[:alpha:]]/$reversed_letters[$index++]/gr;
```
This is the whole solution then:
```perl
use v5.36;
sub reverse_letters( $str ) {
my @reversed_letters = reverse $str =~ /[[:alpha:]]/g;
my $index = 0;
return $str =~ s/[[:alpha:]]/$reversed_letters[$index++]/gr;
}
```
#### **Thank you for the challenge!**