Re: Generating lists of strings
by gmargo (Hermit) on Jan 24, 2010 at 16:57 UTC
|
use Algorithm::Combinatorics qw(variations_with_repetition);
my $length = 4;
my @data = qw(1 2 3);
my $iter = variations_with_repetition(\@data, $length);
while (my $p = $iter->next) {
print join("",@$p)."\n";
}
| [reply] [d/l] |
Re: Generating lists of strings
by jethro (Monsignor) on Jan 24, 2010 at 15:38 UTC
|
Looks like you are counting base 3, but with every digit plus 1, i.e. 0000 becomes 1111 and 2222 becomes 3333
#!/usr/bin/perl
use warnings;
use strict;
my $length=4;
my @number= (1) x $length;
while (@number) {
printnumber(@number);
@number= addto(@number);
}
sub addto {
my @number= @_;
while (1) {
my $carry=1;
foreach (@number) {
$_+= $carry; $carry=0;
if ($_>3) {
$_=1;
$carry=1;
}
}
@number=() if ($carry==1);
return(@number);
}
}
sub printnumber {
my @number= @_;
print reverse(@number),"\n";
}
Your problem is a bit underspecified in that it is not clear if $length should also be a limit to the digits you use. I assumed not.
| [reply] [d/l] |
Re: Generating lists of strings
by BrowserUk (Patriarch) on Jan 24, 2010 at 17:11 UTC
|
#! perl -slw
use strict;
sub nFor(&@) {
my $code = shift;
die "First argument must be a code ref" unless ref( $code ) eq 'CO
+DE';
my @limits = @_;
my @indices = ( 0 ) x @limits;
for( my $i = $#limits; $i >= 0; ) {
$i = $#limits;
$code->( @indices ), ++$indices[ $i ]
while $indices[ $i ] < $limits[ $i ];
$i = $#limits;
$indices[ $i ] = 0, ++$indices[ --$i ]
while $i >= 0 and $indices[ $i ] == $limits[ $i ];
}
}
my @digits = 1 .. 3;
nFor {
print join '', @digits[ @_ ];
} ( 3 ) x 4;
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |
|
|
use Algorithm::Loops qw( NestedLoops );
my @digits = (1..3);
NestedLoops(
[ (\@digits) x 4 ],
sub { print( @_, "\n" ); },
);
Update: In addition to the above, this node originally said that BrowerUk's output was wrong and had code to fix the problem, but I was looking at a reply that produced incorrect output, not the OP. The incorrect version was removed. | [reply] [d/l] [select] |
|
|
NestedLoop. Might as well use it.
Your choice for your code. I much prefer the far simpler syntax of nFor.
And, I think that the mirror between the syntax of nFor and the built-ins map & grep, makes my version far more familiar and digestable (though much less flexible), than the tortuous documentation for NestedLoops which I've still never wrapped by brain around.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] |
|
|
|
|
|
|
|
|
|
|
Re: Generating lists of strings
by Anonymous Monk on Jan 24, 2010 at 15:27 UTC
|
use strict;
use warnings;
use Math::NumberBase;
my $length = 4;
my $b = Math::NumberBase->new($length);
my $start = $b->to_decimal("1" x $length);
my $end = $b->to_decimal("${\($length-1)}" x $length);
print $b->from_decimal($_), "\n" for $start .. $end;
__END__
1111
1112
1113
1120
1121
1122
1123
1130
1131
1132
1133
1200
1201
...
3310
3311
3312
3313
3320
3321
3322
3323
3330
3331
3332
3333
| [reply] [d/l] |
|
|
And in the spirit of jethro's analysis, here's a simpler method:
my $length = 4;
my $b = Math::NumberBase->new($length-1);
my $start = 0;
my $end = $b->to_decimal("${\($length-2)}" x $length);
print "$_\n" for
map {join'', map {$_+1} split(//,$b->from_decimal($_))}
$start .. $end;
| [reply] [d/l] |
|
|
Sorry, I missed that you have no ending zeros. This change recreates the desired output:
print $b->from_decimal($_), "\n" for
grep { $_ % $length }
$start .. $end;
| [reply] [d/l] |
Re: Generating lists of strings
by johngg (Canon) on Jan 24, 2010 at 22:31 UTC
|
$ perl -E '
> @digits = ( 1 .. 3 );
> $length = 4;
> $globStr = qq{{@{ [ join q{,}, @digits ] }}} x $length;
> say for glob $globStr;'
1111
1112
1113
1121
1122
1123
1131
1132
1133
1211
1212
1213
1221
1222
1223
1231
1232
1233
1311
1312
1313
1321
1322
1323
1331
1332
1333
2111
2112
2113
2121
2122
2123
2131
2132
2133
2211
2212
2213
2221
2222
2223
2231
2232
2233
2311
2312
2313
2321
2322
2323
2331
2332
2333
3111
3112
3113
3121
3122
3123
3131
3132
3133
3211
3212
3213
3221
3222
3223
3231
3232
3233
3311
3312
3313
3321
3322
3323
3331
3332
3333
$
I hope this is useful.
| [reply] [d/l] |