# first the sequences to test my @sequences = ( [qw(1 2 3 4 5)], # start at 1, inc by 1 [qw(1 3 5 7 9)], # start at 1, inc by 2 [qw(0 1 0 1 0)], # start at 0, alternate 0/1 [qw(2 1 0 -1 -2)] # start at 2, dec by 1 ); # the functions to test them against - each one should # match just one of the sequences above my @functions =( { text => 'start at 1, increment by 1', start => 1, function => sub { $_[0] + 1 } }, { text => 'start at 1, increment by 2', start => 1, function => sub { $_[0] + 2 } }, { text => 'start at 0, alternate 0/1', start => 0, function => sub { ($_[0] == 0) ? 1 : 0 } }, { text => 'start at 2, decrement by 1', start => 2, function => sub { $_[0] - 1 } } ); foreach my $function (@functions) { print $function->{text}."\n"; foreach my $sequence (@sequences) { print ' '; print 'not ' unless( checksequence( @{$sequence}, $function->{start}, $function->{function} ) ); print 'ok ['.join(', ', @{$sequence})."]\n"; } } # takes a sequence, the desired start value, and the # function to generate the next correct value sub checksequence { # the sequence is the most important parameter, so # i pass it first. my($f, $z, @seq) = reverse(@_); @seq = reverse(@seq); # check that the first value is correct return 0 unless(shift(@seq) == $z); # now see if any subsequent values are wrong and # if they are, return immediately foreach my $value (@seq) { return 0 unless(($z = $f->($z)) == $value); } 1; }