The one about regular expressions
Tags: perl, python, theweeklychallenge
Published: 2023-10-22 03:37:45

## Weekly Challenge 239

Each week Mohammad S. Anwar sends out [The Weekly Challenge](https://theweeklychallenge.org/), a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.

[Challenge](https://theweeklychallenge.org/blog/perl-weekly-challenge-239/), [My solutions](https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-239/sgreen)

## Task 1: Same String

### Task

You are given two arrays of strings.

Write a script to find out if the word created by concatenating the array elements is the same.

### My solution

Both of this weeks solutions involve regular expressions, but this one is definitely a hack. But that is what regex is for, isn't it? :)

Sometimes the challenge in these tasks is how to parse the input. Most of the items it's just a list, and we can retrieve that for `sys.argv` (`@ARGV` in Perl). When it's two lists, it's a bit harder. We could accept a JSON list, but that is a little overkill for this.

For this task, I take two inputs from the command line. I then strip everything that isn't a letter, and then compare the values. This allows the inputs to be a list, space separate or whatever format the user chooses.

```python
if re.sub('[^a-z]', '', lists[0], flags=re.IGNORECASE) == \
        re.sub('[^a-z]', '', lists[1], flags=re.IGNORECASE):
    print('true')
else:
    print('false')
```

The Perl code runs the regular expression `s/[^a-z]//gi` on each value and compares the resulting string.

### Examples

```bash
$ ./ch-1.py '("ab", "c")' '("a", "bc")'
true

$ ./ch-1.py '("ab", "c")' '("ac", "b")'
false

$ ./ch-1.py '("ab", "cd", "e")' '("abcde")'
true
```

## Task 2: Consistent Strings

### Task

You are given an array of strings and allowed string having distinct characters.

A string is consistent if all characters in the string appear in the string allowed.

Write a script to return the number of consistent strings in the given array.

### My solution

This one of those times that the Python and Perl solution are different. The Perl solution would have worked in Python. As I write the Python code first, I stuck with the code that I originally wrote.

For the Python solution, I turn the string into a regular expression - [escaping](https://docs.python.org/3/library/re.html#re.escape) special characters. Then I count the words that match the regular expression.

```python
r = f'^[{re.escape(allowed)}]+$'
count = sum(1 for word in words if re.search(r, word))
```

Perl doesn't have a built-in escape function. This means if the allowed characters were `a`, `-` and `z`, it would be interpreted as the 26 letters of the alphabet, rather than the three characters. And I definitely don't feel like writing my own escape function.

For the Perl solution, I created a hash called `allowed` that contains each character of the allowed word. I then iterate over the word list, and check that all letters are in the `allowed` hash.

```perl
my %allowed = map { $_, 1 } split(//, $allowed);

foreach my $word (@words) {
    $count++ if all { exists $allowed{$_} } split(//, $word);
}
```

### Examples

```bash
$ ./ch-2.py ad bd aaab baa badab ab
2

$ ./ch-2.py a b c ab ac bc abc abc
7

$ ./ch-2.py cc acd b ba bac bad ac d cad
4
```