The Bear's Den

Enter at your own risk

From Start to End and Back

Task 1: Reverse Existence

Submitted by: Mohammad Sajid Anwar


You are given a string.

Write a script to find whether any substring of length 2 is also present in the reverse of the given string.

Example 1

Input: $str = "abcba"
Output: true

Reverse of given string is "abcba".
The substring "ab" in original string is also present in the reverse string too.

Example 2

Input: $str = "racecar"
Output: true

The substring "ce" is present in both.

Example 3

Input: $str = "abcd"
Output: false

Example 4

Input: $str = "banana"
Output: true

The substring "an" is present in both.

Example 5

Input: $str = "hello"
Output: true

The substring "ll" is present in both.

Solution

As the substring length of 2 looks kind of arbitrary, I’ll generalize the task to any given length.

Perl

Use a captured look-ahead assertion as the sliding substring and step forward until the substring is a substring of the reversed string or the end of the string is reached.

use strict;
use warnings;
use experimental 'signatures';

sub reverse_ex ($str, $length) {
    my $rev = reverse $str;

    0 + ($str =~ /(?=(.{$length})).(?(?{index($rev, $1) < 0})(*FAIL))/);
}

See the full solution to task 1.

J

A tacit verb is probably not the best solution for this task as we want to apply a dyadic verb to infixes of a noun. However, the “infix” adverb \ produces a dyadic verb u\ where the left argument specifies the infix size and therefore u can operate as a monad only.

One solution is to bond one noun argument to the dyad, transforming it into a monad. Unfortunately, this operation cannot be done tacitly, but here the non-tacit part may be encapsulated in a conjunction.

Building a monadic verb from named parts:

Finally:

reverse_ex =: adverb define
   infix_dyad =. conjunction : 'n&(x&u\) y'
   any =. +./
   substr_in =. any @: E.~
   reverse =. |.

   ([: any reverse substr_in infix_dyad m ]) f. : [:
)

Obviously, the resulting verb (here for m=:2) is a bit more complex:

   2 reverse_ex
([: +./ |. +./@:E.~ (2 : (':'; 'n&(x&u\) y')) 2 ]) :[:

Applying different lengths:

   2 reverse_ex 'banana'
1
   5 reverse_ex 'banana'
1
   6 reverse_ex 'banana'
0

See the full solution.

Task 2: Prefix Suffix

Submitted by: Mohammad Sajid Anwar


You are given an array of strings.

Write a script to find if the two strings (str1, str2) in the given array such that str1 is prefix and suffix of str2. Return the total count of such pairs.

Example 1

Input: @array = ("a", "aba", "ababa", "aa")
Output: 4

$array[0], $array[1]: "a" is a prefix and suffix of "aba"
$array[0], $array[2]: "a" is a prefix and suffix of "ababa"
$array[0], $array[3]: "a" is a prefix and suffix of "aa"
$array[1], $array[2]: "aba" is a prefix and suffix of "ababa"

Example 2

Input: @array = ("pa", "papa", "ma", "mama")
Output: 2

$array[0], $array[1]: "pa" is a prefix and suffix of "papa"
$array[2], $array[3]: "ma" is a prefix and suffix of "mama"

Example 3

Input: @array = ("abao", "ab")
Output: 0

Example 4

Input: @array = ("abab", "abab")
Output: 1

$array[0], $array[1]: "abab" is a prefix and suffix of "abab"

Example 5

Input: @array = ("ab", "abab", "ababab")
Output: 3

$array[0], $array[1]: "ab" is a prefix and suffix of "abab"
$array[0], $array[2]: "ab" is a prefix and suffix of "ababab"
$array[1], $array[2]: "abab" is a prefix and suffix of "ababab"

Example 6

Input: @array = ("abc", "def", "ghij")
Output: 0

Solution

Making some assumptions about the solution:

  1. An array element is not checked against itself. This follows from all examples.
  2. A pair of equal elements counts only once. This follows from example 4.
  3. The elements’ order in the array is not significant. This is not explicitly specified and I consider the ordered examples as accidental.

A string x cannot be prefix or suffix of a string y if x’s length exceeds y’s. Sorting the array by increasing string length therefore permits a pure “look ahead” check. This way, all of the above assumptions can be fulfilled easily.

Perl

Using a regex to test the prefix and suffix relation and loop strictly forward.

use strict;
use warnings;

sub count_prefix_suffix {
    my @arr = sort {length($a) <=> length($b)} @_;
    my $count = 0;
    while (my $head = shift @arr) {
        $head = quotemeta $head;
        $count += /^(?=$head).*$head$/ for @arr;
    }

    $count;
}

See the full solution to task 2.

J

In the following the term suffix appears in two contexts:

Using array suffix for the latter.

Building the final tacit verb from named parts:

Finally:

count_pre_suf =: _(adverb define)
   matches =. E.
   from =. {
   idx_ps =. 0 , -@#@[
   all =. *./
   pre_suf =. [: all idx_ps from matches

   sort_by_length =. /: #@>
   over_suffices =. ({.` `}.)`:6 \.
   open =. &>
   flat =. ,
   sum =. +/

   sum @: flat @: (pre_suf open over_suffices) @ sort_by_length f. : [:
)

The final verb:

   count_pre_suf
+/@:,@:(({. ([: *./ (0 , -@#@[) {  E.)&> }.)\.)@(/: #@>) :[:

See the full solution.