in reply to Iterating through string combinations

If you can't get rid of the recursion, you could always tighten up the program. If you create a mapping of characters to their next character, look how short your final subroutine becomes:

#!/usr/bin/perl -w use strict; my $number = '000'; my %mapping; @mapping{ 0..9,'a'..'z' } = ( 1..9,'a'..'z','0' ); do { increment( \$number ); print "$number\n"; } until $number eq 'zzzzzzzzzzzzzzzz'; # or some other long string sub increment { my ( $number_ref ) = @_; my @digits = split //, $$number_ref; unshift @digits, undef while @digits < 16; _increment_digit( \@digits, @digits - 1 ); $$number_ref = join '', grep { defined } @digits; } sub _increment_digit { my ( $array_ref, $index ) = @_; $array_ref->[$index] ||= 0; $array_ref->[$index] = $mapping{ $array_ref->[$index] }; _increment_digit( $array_ref, ($index - 1) ) if $array_ref->[$inde +x] eq 'z'; }

Cheers,
Ovid

Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Replies are listed 'Best First'.
Re: (Ovid) Re: Iterating through string combinations
by atcroft (Abbot) on Dec 18, 2001 at 05:13 UTC

    Would the following modifications to Ovid's code (above) make it more flexible, or am I deluding myself? I would think then a modification to change sizes would be much easier.

    • Add my $startwith = 3, $endafter = 16; before line 4
    • In line 11, change 'zzzzzzzzzzzzzzzz' to read ('z' x $endafter);
    • In line 18, replace 16 with $endafter

    As to what you wish to do with the code, assuming you are only doing the range (0..9,a..z), you are performing the number of iterations equal to the summation of (36^n) for n from 3 to 16, which is a little less than 7.96e24 (but more than simply (36^16)). To give some perspective to it (if that can be done), if you can perform 1 billion loops per second, you can expect it to take approximately 252 million years to complete them all. Do you really want to do that?

    Comments? Guidance?