# ETOOBUSY š minimal blogging for the impatient

# PWC082 - Interleave String (now for real, hopefully!)

**TL;DR**

On we go with TASK #2 of Perl Weekly Challenge #082. Again.

In PWC082 - Interleave String (but not really!) I attempted a solution
to the challengeā¦ but it turned out to be a *different* one.. Letās
try againā¦

# The challenge

Nothing really new here:

You are given 3 strings;

`$A`

,`$B`

and`$C`

. Write a script to check if`$C`

is created by interleave`$A`

and`$B`

. Print 1 if check is success otherwise 0.

BUT the examples - when read with due care and without pre-conceptions -
are explicity in showing that you can get as many characters out of
either `$A`

and `$B`

at any given step, not only one. Which was,
unfortunately, my assumption in the previous solution. Oooops š

# The questions

At this point, I interpet the *interleave* as any sequence of pieces
taken from either string, up to their complete consumption. Again, Iāll
assume that itās at the character level, whatever `substr`

deems OK is
fine by me.

# The solution

This time the problem is more general and we can reason like this: the
first character of `$C`

can come from either `$A`

or `$B`

. Thatās it,
problem solved, see ya!

Ohā¦ was that a tad *cryptic*?!? š§

Letās assume the three strings are non-empty, they will have the form of
*a first character, followed by the rest of the string*:

```
$A <=> $first_A . $rest_A
$B <=> $first_B . $rest_B
$C <=> $first_C . $rest_C
```

As we said, `$first_C`

must be equal to either `$first_A`

or `$first_B`

for the interleave to apply. Letās say itās equal to `$first_A`

: if we
cancel out both of them, we are left with:

```
$A1 <=> $rest_A
$B1 <=> $first_B . $rest_B
$C1 <=> $rest_C
```

and `$C1`

must be the interleave of `$A1`

and `$B1`

, or the interleave
will not apply to the initial triple as well. The same reasoning can be
done if `$first_C`

is actually coming from `$B`

(i.e. `$first_B`

) so we
will not repeat it.

This can be easily addressed recursively, because itās sufficient to
re-apply the process to `$A1`

, `$B1`

, and `$C1`

at this point. When
`$first_C`

can come from both `$A`

and `$B`

, it will be sufficient to
try both paths: if one fails, we check the other one.

A recursive function, though, must have a stop condition. In our case, when any of the strings are empty, thereās no more āinterleavingā to do and we check the remainders against each other: if they match itās a win, otherwiseā¦ not.

So weāre ready to code the core of the solution:

```
sub iir ($A, $B, $C) {
return 1 if (length($A) == 0 && $B eq $C) # only B remained
|| (length($B) == 0 && $A eq $C) # only A remained
|| (length($C) == 0); # never reached, paranoia
my $cc = substr $C, 0, 1, ''; # chop off first char from $C...
return (($cc eq substr $A, 0, 1) && iir(substr($A, 1), $B, $C))
|| (($cc eq substr $B, 0, 1) && iir(substr($B, 1), $A, $C));
}
```

The initial check is exactly the last one we discussed about the length
of any string having dropped to zero. The last check (on `$C`

) is to
account for `$C`

having dropped to zero length while there are still
characters in either of the other two inputs, but itās a paranoia
because we wrap the above function in this:

```
sub is_interleaving ($A, $B, $C) {
return (length($A) + length($B) == length($C)) && iir($A, $B, $C);
}
```

This check is a leftover from our previous version, and basically does a
quick check on the lengths before running the more costly recursive
function. For this reason, the check on the length of `$C`

inside
function `iir`

becomes unnecessary (but still can remain because it will
not get in the way).

Hereās the (new) complete script if you want to play with it:

```
#!/usr/bin/env perl
use 5.024;
use warnings;
use English qw< -no_match_vars >;
use experimental qw< postderef signatures >;
no warnings qw< experimental::postderef experimental::signatures >;
# well... let's recurse!
sub iir ($A, $B, $C) {
return 1 if (length($A) == 0 && $B eq $C) # only B remained
|| (length($B) == 0 && $A eq $C) # only A remained
|| (length($C) == 0); # never reached, paranoia
my $cc = substr $C, 0, 1, ''; # chop off first char from $C...
return (($cc eq substr $A, 0, 1) && iir(substr($A, 1), $B, $C))
|| (($cc eq substr $B, 0, 1) && iir(substr($B, 1), $A, $C));
}
sub is_interleaving ($A, $B, $C) {
return (length($A) + length($B) == length($C)) && iir($A, $B, $C);
}
my $A = shift || 'XY';
my $B = shift || 'Z';
my $C = shift || 'ZXY';
say is_interleaving($A, $B, $C);
```

Before closing, Iād like to thank Myoungjin Jeon again for spotting the errors in my previous interpretation of this task and until next timeā¦ have a good day!