Re: In need of a sequence iterator.
by !1 (Hermit) on Dec 02, 2004 at 07:26 UTC
|
sub genIterator {
my ($len,$count) = @_;
my @list = ();
return sub {
if (@list == 0 || @list < $len) {
push @list, 0;
} else {
$list[-1]++;
while (@list && $list[-1] >= $count) {
pop @list;
$list[-1]++ if @list;
}
}
return @list ? join("", @list) : undef;
}
}
Note that the code to iterate should be:
my $iter = genIterator(4,3);
print while defined($_ = $iter->());
since 0 evaluates as false. | [reply] [d/l] [select] |
|
|
| [reply] |
|
|
sub genIterator {
my ($len,$array) = @_;
$array = [0..$array-1] if $array =~ /^\d+$/;
die "Don't know what to do with $array" unless ref $array eq "ARRA
+Y";
my @list = ();
return sub {
return undef unless @$array;
if (@list < $len) {
push @list, 0;
} else {
$list[-1]++;
while (@list && $list[-1] >= @$array) {
pop @list;
$list[-1]++ if @list;
}
}
return @list ? join("", @$array[@list]) : undef;
}
}
| [reply] [d/l] |
|
|
sub genIterator {
my($len, $count) = @_;
my $cur = '';
my $lastdig = $count - 1;
return sub {
if (length($cur) < $len) {
$cur .= '0';
} else {
$cur =~ s/([^$lastdig])$lastdig*\z/$1 + 1/e
or $cur = undef;
}
$cur;
}
}
Of course this assumes $count doesn't exceed 10; this approach gets a bit more complex if you need to deal with larger bases.
Hugo | [reply] [d/l] [select] |
|
|
The $count can get upto 255 (and theoretically beyond with unicode). The numbers are eventually packed to form a binary string of codepoints that increment, magic string auto-increment style, but starting at chr(0) and modulo alphabet size.
I'm currently limiting my thinking to 8-bit ascii bytes, but notionally the alphabet could be larger with unicode.
The actual keys involved (made up from an arbitrary alphabet) are translated to chr(0) ... chr(alphabet max).
Examine what is said, not who speaks.
"But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
"Think for yourself!" - Abigail
"Time is a poor substitute for thought"--theorbtwo
"Efficiency is intelligent laziness." -David Dunham
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
| [reply] |
|
|
Re: In need of a sequence iterator.
by ikegami (Patriarch) on Dec 02, 2004 at 07:38 UTC
|
use strict;
use warnings;
sub genIterator_helper($\@) {
my ($base, $list) = @_;
my $i = $#$list;
for (;;) {
last if (++$$list[$i] < $base);
$$list[$i] = 0;
return undef unless $i;
$i--;
}
return 1;
}
sub genIterator {
my ($max_digits, $base) = @_;
my @list;
foreach my $num_digits (1..4) {
my @digits = (0) x $num_digits;
do {
push(@list, join('', @digits));
} while (genIterator_helper($base, @digits));
}
@list = sort { $a cmp $b } @list;
return sub { shift(@list) };
}
my $iter = genIterator(4, 3);
print "$_$/" while defined ($_ = $iter->());
| [reply] [d/l] |
Re: In need of a sequence iterator. (NestedLoops)
by tye (Sage) on Dec 02, 2004 at 23:10 UTC
|
#!/usr/bin/perl -w
use strict;
use Algorithm::Loops qw( NestedLoops );
sub genIter
{
my( $len, $base )= @_;
return scalar NestedLoops(
[ ( [ 0 .. ($base-1) ] ) x $len ],
{ OnlyWhen => 1 },
);
}
my( $len, $base )= ( @ARGV, 4, 3 );
my $iter= genIter( $len, $base );
my @list;
while( @list= $iter->() ) {
print @list, $/;
}
| [reply] [d/l] |
Re: In need of a sequence iterator.
by Zed_Lopez (Chaplain) on Dec 02, 2004 at 07:08 UTC
|
| [reply] |
|
|
#! perl -slw
use strict;
sub gen {
my( $len, $depth ) = @_;
return () unless $len;
return map {
my $pre = $_;
( $pre, map{ $pre . $_ } gen( $len -1, $depth ) );
} 0 .. $depth - 1;
}
print for gen( 4, 3 );
Examine what is said, not who speaks.
"But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
"Think for yourself!" - Abigail
"Time is a poor substitute for thought"--theorbtwo
"Efficiency is intelligent laziness." -David Dunham
"Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
| [reply] [d/l] |
Re: In need of a sequence iterator. (Haskell)
by kelan (Deacon) on Aug 08, 2005 at 20:38 UTC
|
I solved this question on my own in Haskell at the time it was posted. It involved using a couple nested maps and some other things that were quite complicated to get my head around (as I remember). However, recently I've been experimenting with using lists as monads, and found my solution to this puzzle. Reworking it from that point of view, it becomes nice and clear. I know you're dabbling with Haskell, so I thought you might be interested.
import Char -- for intToDigit
gen :: Int -> Int -> [String]
gen 0 _ = []
gen len max = do
d <- map intToDigit [0 .. max-1]
ds <- [] : gen (len-1) max
return (d:ds)
Below is the first version I came up with. You might not want to read it. It's rather ungainly.
gen :: Int -> Int -> [String]
gen 0 _ = []
gen len max =
concat (
map (
\digit -> [digit] : (
map ( digit : )
( gen (len - 1) max )
)
)
( map intToDigit [0 .. max-1] )
)
| [reply] [d/l] [select] |
|
|
I've pretty much given up on Haskell. It's fine if all you want to do is prove that your new variation of Fibonacci compiles okay, but if you want to actually see the output, forget it. Much less if you want to read your data from an external source.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
"Science is about questioning the status quo. Questioning authority".
The "good enough" maybe good enough for the now, and perfection maybe unobtainable, but that should not preclude us from striving for perfection, when time, circumstance or desire allow.
| [reply] [d/l] |