# Odo.pm ovedpo15 pm #11145308 06jul22waw package Odo; use strict; use warnings; use Data::Dump qw(dd); # for debug sub Iterator (&) { return $_[0]; } # syntactic sugar per mjd (Dominus) sub odometer { my ($string, # string to permute @special_chars, # single, special characters to use in "odometer" ) = @_; # offsets in string of individual whitespace characters. my @offsets; push @offsets, $-[0] while $string =~ m{ \s }xmsg; # dd '-----', $string, \@offsets; # for debug die "too few special characters to replace all whitespace found" if @special_chars < @offsets; # minimal validation # init odo counter for each offset plus overflow flag (inited false). my @odo_offsets = ((0) x @offsets, 0); # iterator to generate each string permutation. return Iterator { # return undef if odo overflowed (iterator permanently exhausted). return if $odo_offsets[-1]; # overflow flag true my $permutation = $string; # possible string permutation # dd '+++++', \@odo_offsets; # ; # for debug # replace each whitespace char with permuted special character. substr $permutation, $offsets[$_], 1, $special_chars[$odo_offsets[$_]] for 0 .. $#offsets; # increment odometer for next permutation; flag odo overflow. $odo_offsets[$_] < $#special_chars ? ($odo_offsets[$_]++, last) : ($odo_offsets[$_] = 0) for 0 .. $#odo_offsets; # dd '_____', \@odo_offsets; ; # for debug return $permutation; }; # end path permutation Iterator } # end sub odometer() 1;