#!/usr/bin/perl
use strict;
use warnings;
# The loop has been added for easy verification of multiple inputs
# Read the line with the lengths and convert it into an array
my $line = <>;
my @lengths = split /\s+/, $line;
# Create a regex pattern from the lengths. It begins with any number of
# non 'x' or '_' characters
my $re = '[x_]*';
for (@lengths) {
# Example: if a length was 3, then the pattern will be appended with
# ([#_]{3})[x_]+ which matches a 3 character combination of '#' and '_'
# and then 'x's (spaces) or '_'s (unkown characters) after that
$re .= "([#_]{$_})[x_]+";
}
# Replace the last + with * since we don't need to have non '#' characters
# at the end
$re =~ s/\+$/*/;
# Read the pattern and remove the new line
my $pat = <>;
# At every index of this array is a concatenation of all patterns that matched
# the length at that index
my @matched_parts;
{
# We need to be less strict to use $$_ (i.e. $1, $2, $3 etc) which are
# the groups captured during the regex match
# The complete pattern is matched with the regex generated earlier -
# hence the ^..$.
#
# The code within (?{...}) is executed if the regex matched
# successfully. Inside the code, we append the matched sub-patterns ($1
# for the first length, $2 for the second etc) for every length to the
# right element inside @matched_parts. $$_ will result in $1, $2, $3
# etc for $_ = 1, 2, 3 etc.
#
# The (?!) at the end - i.e. a negative look ahead with no characters -
# ensures that after the generated regex matches successfully, the
# complete pattern match still fails, thus forcing the regex engine to
# backtrack. This way, we iterate over all possible matches of the 1st
# part and execute the code for them.
$pat =~ /
^$re$ # match the complete pattern with the constructed regex
(?{ # code to execute on successful match. the comma is only added
# for clarity
$matched_parts[$_-1].=",$$_" for 1..@lengths
})
(?!) # fail the match after the code is executed
/x;
# Uncomment the following to see the value of @matched_parts
#use Data::Dumper;
#$Data::Dumper::Terse = 1;
#$Data::Dumper::Indent = 3;
#print "Matched Parts: " . Dumper(\@matched_parts);
}
if (@matched_parts) {
# We have a match, so the lengths can be fitted inside the pattern.
# Now to see if there are any unambiguous matches
for (0..$#lengths) {
# For every length, check if @matched_parts does not have any
# '_' characters in the corresponding index. This means that only
# '#' characters have matched every time implying that there are
# no ambiguities. Print such indices.
print "$_ " if $matched_parts[$_] !~ /_/; }
} else {
}
}