Here's another single-regex approach, although as others have said, I don't necessarily think such an approach is best. (Requires Perl version 5.10+.)
use 5.010; # needs (?(?{ code... })true-pattern) and (*F) extensions
use warnings;
use strict;
use Test::More
# tests => ?? + 1 # Test::NoWarnings adds 1 test
'no_plan' # safer to use done_testing()
;
use Test::NoWarnings;
# use Data::Dump qw(dd pp);
# BEGIN { use_ok 'SomeModule', qw(some functions); }
# test datasets ####################################################
use constant TEST_VECTOR_SET_1 => (
"no repeating groups found",
[ '', ],
[ 'A', ],
[ 'AA', ],
[ 'AbA', ],
[ 'ABC', ],
"one group found",
[ 'AAA', 'AAA' ],
[ 'AbAcA', 'AbAcA' ],
[ 'xAbAcA', 'AbAcA' ],
[ 'AbAcAx', 'AbAcA' ],
[ 'xAbAcAx', 'AbAcA' ],
[ 'AbcAdeA', 'AbcAdeA' ],
[ 'xAbcAdeA', 'AbcAdeA' ],
[ 'AbcAdeAx', 'AbcAdeA' ],
[ 'xAbcAdeAx', 'AbcAdeA' ],
[ 'BcBdeBAAA', 'AAA' ],
"two or more groups found",
[ 'AAAAAA', 'AAA', 'AAA', ],
[ 'AbAcAAbAcA', 'AbAcA', 'AbAcA', ],
[ 'AbAcAAdeAfgA', 'AbAcA', 'AdeAfgA', ],
[ 'AbAcABdeBfgBChijCklmC', 'AbAcA', 'BdeBfgB', 'ChijCklmC', ],
[ 'AbAcA BdeBfgB ChijCklmC', 'AbAcA', 'BdeBfgB', 'ChijCklmC', ],
[ 'AAbAcAABdeBfgBBCChijCklmCC', 'AbAcA', 'BdeBfgB', 'ChijCklmC', ],
"some test cases from pm#1176775 post",
[ 'x1x2x...x', 'x1x2x', '...', ], # pm#1176786
);
# functions under test #############################################
sub periodic_1 {
my ($string,
) = @_;
my @found;
push @found, $1 while $string =~ m{
( # capture entire rep group to $1
(.) # capture rep char to $2
((?: (?: (?! \2) .)* \2)) # capture 1st rep to $3
((?: (?: (?! \2) .)* \2)) # capture 2nd rep to $4
(?(?{ length($3) != length($4) }) (*F)) # same rep lengths
)
}xmsg;
return @found;
}
# testing, testing... ##############################################
FUNT:
for my $ar_funt (
# function
# name comment
[ 'periodic_1', ],
) {
my ($func_name, $func_note) = @$ar_funt;
*periodic = do { no strict 'refs'; *$func_name; };
defined $func_note ? note "\n $func_name() -- $func_note \n\n"
: note "\n $func_name() \n\n"
;
VECTOR:
for my $ar_vector (TEST_VECTOR_SET_1) {
if (not ref $ar_vector) { # comment string if not vector ref.
note $ar_vector;
next VECTOR;
}
my ($string, @expected) = @$ar_vector;
my $cmnt_str = join ' ', map "'$_'", @expected;
is_deeply [ periodic($string) ], [ @expected ],
"'$string' -> ($cmnt_str)",
;
} # end for VECTOR
} # end for FUNT
note "\n done testing functions \n\n";
done_testing();
exit;