Algorithm-Odometer-Tiny

 view release on metacpan or  search on metacpan

lib/Algorithm/Odometer/Gray.pm  view on Meta::CPAN

#!perl
use warnings;
use strict;

# SEE THE END OF THIS FILE FOR AUTHOR, COPYRIGHT AND LICENSE INFORMATION

{ package Algorithm::Odometer::Gray;
	our $VERSION = "0.04";
	use Carp;
	use overload '<>' => sub {
		my $self = shift;
		return $self->() unless wantarray;
		my @all;
		while (defined( my $x = $self->() ))
			{ push @all, $x }
		return @all;
	};
	sub new {  ## no critic (RequireArgUnpacking)
		my $class = shift;
		return bless odometer_gray(@_), $class;
	}
	sub odometer_gray {  ## no critic (RequireArgUnpacking)
		croak "no wheels specified" unless @_;
		my @w = @_;
		croak "all wheels must have at least two positions"
			if grep {@$_<2} @w;
		my @c = (0) x @w;
		my @f =  0 .. @w;
		my @o = (1) x @w;
		my $done;
		return sub {
			if ($done) { @c = (0) x @w; @f =  0 .. @w; @o = (1) x @w; $done=0; return }
			my @cur = map {$w[$_][$c[$_]]} 0..$#w;
			if ($f[0]==@w) { $done=1 }
			else {
				my $j = $f[0]; $f[0] = 0;
				$c[$j] += $o[$j];
				if ( $c[$j]==0 || $c[$j]==$#{$w[$j]} ) {
					$o[$j] = -$o[$j];
					$f[$j] = $f[$j+1];
					$f[$j+1] = $j+1;
				}
			}
			return wantarray ? @cur : join '', map {defined()?$_:''} @cur;
		};
	}
}

1;
__END__

=head1 Name

Algorithm::Odometer::Gray - Generate a "n-ary" / "non-Boolean" Gray code sequence (Cartesian product / product set)

=head1 Synopsis

 use Algorithm::Odometer::Gray;
 my $odometer = Algorithm::Odometer::Gray->new( ['a','b','c'], [1,2] );
 print "$_ " while <$odometer>;
 print "\n";
 # => prints the sequence "a1 b1 c1 c2 b2 a2"

=head1 Description

This class implements the permutation algorithm described in I<[1]>
and I<[2]>. It differs from L<Algorithm::Odometer::Tiny|Algorithm::Odometer::Tiny>
only in the order of the generated sequence, so
B<< for all details about usage etc. please see L<Algorithm::Odometer::Tiny> >>.

=head2 Example

The following wheels:

 ["Hello","Hi"], ["World","this is"], ["a test.","cool!"]

produce this sequence:

 ("Hello", "World",   "a test.")
 ("Hi",    "World",   "a test.")



( run in 2.506 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )