Re: How to return a list using recursion?
by BrowserUk (Patriarch) on Aug 07, 2012 at 04:53 UTC
|
sub chunks{
my( $n, @in ) = @_;
join ",\n", map join(' ', splice @in, 0, $n), 0 .. $#in / $n;
};;
print chunks( 3, 'a'..'z' );;
a b c,
d e f,
g h i,
j k l,
m n o,
p q r,
s t u,
v w x,
y z
print chunks( 10, 'a'..'z' );;
a b c d e f g h i j,
k l m n o p q r s t,
u v w x y z
print chunks( 26, 'a'..'z' );;
a b c d e f g h i j k l m n o p q r s t u v w x y z
print chunks( 13, 'a'..'z' );;
a b c d e f g h i j k l m,
n o p q r s t u v w x y z
print chunks( 6, 'a'..'z' );;
a b c d e f,
g h i j k l,
m n o p q r,
s t u v w x,
y z
With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
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".
| [reply] [d/l] |
Re: How to return a list using recursion?
by tobyink (Canon) on Aug 07, 2012 at 05:45 UTC
|
I agree that this isn't necessarily the best task to use recursion for, but here's one possibility:
use Data::Dumper;
sub mk_chunker
{
my $n = shift;
die unless $n > 0;
my $sub;
return $sub = sub {
return \@_ if @_ < $n;
return (
[ @_[0..$n-1] ],
$sub->(@_[$n..$#_]), # recursion
);
};
}
*chunk_5 = mk_chunker(5);
print Dumper chunk_5('a' .. 'z');
The closure in mk_chunker is a good candidate for Perl 5.16's new __SUB__ feature...
use 5.016;
sub mk_chunker
{
my $n = shift;
die unless $n > 0;
return sub {
return \@_ if @_ < $n;
return (
[ @_[0..$n-1] ],
__SUB__->(@_[$n..$#_]), # recursion
);
};
}
perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'
| [reply] [d/l] [select] |
Re: How to return a list using recursion?
by Athanasius (Archbishop) on Aug 07, 2012 at 02:38 UTC
|
#! perl
use strict;
use warnings;
my @list = ( 'a' .. 'z' );
my @array_chunk5 = _array_chunk5( @list );
print "Array chunk of 5 =\n";
my $count;
print "Chunk ", ++$count, ":\n", join("\n", @$_), "\n\n" for @array_ch
+unk5;
sub _array_chunk5
{
my @arr = @_;
if (@arr > 5)
{
my @chunk;
push(@chunk, shift @arr) for (1 .. 5);
return ( \@chunk, _array_chunk5(@arr) );
}
else
{
return \@arr;
}
}
HTH,
Athanasius <°(((>< contra mundum
| [reply] [d/l] |
Re: How to return a list using recursion?
by johngg (Canon) on Aug 07, 2012 at 11:06 UTC
|
Another recursive solution using a subroutine that takes a block of code to execute against a "chunked" list.
use strict;
use warnings;
use 5.010;
sub groupsOf (&$@);
my @list = ( q{a} .. q{z} );
say for groupsOf { qq{@_,} } 5, @list;
say for groupsOf { qq{@_,} } 7, @list;
sub groupsOf (&$@)
{
my $rcToRun = shift;
my $groupsOf = shift;
my $rcDoIt;
$rcDoIt = sub
{
$rcToRun->(
map shift, 1 .. ( @_ < $groupsOf ? @_ : $groupsOf )
),
@_ ? &$rcDoIt : ();
};
&$rcDoIt;
}
I hope this is of interest.
Update: Oops, forgot to post the output :-(
a b c d e,
f g h i j,
k l m n o,
p q r s t,
u v w x y,
z,
a b c d e f g,
h i j k l m n,
o p q r s t u,
v w x y z,
| [reply] [d/l] [select] |
Re: How to return a list using recursion?
by Anonymous Monk on Aug 07, 2012 at 03:39 UTC
|
Well, this isn't something you should use recursion for
#!/usr/bin/perl --
use strict; use warnings;
use Data::Dump;
use List::AllUtils qw' natatime ';
my @x = ('a' .. 'z');
my $it = natatime 5, @x;
my @yo;
while (my @vals = $it->())
{
push @yo, "@vals,\n";
}
chomp $yo[-1];
chop $yo[-1];
dd \@yo;
__END__
[
"a b c d e,\n",
"f g h i j,\n",
"k l m n o,\n",
"p q r s t,\n",
"u v w x y,\n",
"z",
]
| [reply] [d/l] |
|
|
#! perl
use strict;
use warnings;
my @list = ('a' .. 'z');
my $size = 5;
_array_chunk_it($size, @list);
while (my @chunk = _array_chunk_it())
{
print "Array chunk of $size =\n", join("\n", @chunk), "\n\n";
}
{
my ($array, $count);
sub _array_chunk_it
{
my @chunk;
if (@_)
{
$count = shift;
$array = [ @_ ];
}
else
{
for (1 .. $count)
{
push(@chunk, shift @$array) if @$array;
}
}
return @chunk;
}
}
(With newer versions of Perl, this can be rewritten using state.)
TMTOWTDI :-)
Update: ++Anonymous Monk for the superior version using a closure, below.
Athanasius <°(((>< contra mundum
| [reply] [d/l] |
|
|
use strict;
use warnings;
my @list = ('a' .. 'z');
my $size = 5;
my $chunker = _array_chunk_it($size, @list);
while (my @chunk = $chunker->())
{
print "Array chunk of $size =\n", join("\n", @chunk), "\n\n";
}
sub _array_chunk_it {
my ($count, @array) = @_;
return sub {
my @chunk;
for (1 .. $count) {
push(@chunk, shift @array) if @array;
}
return @chunk;
}
}
(Using a closure we can actually call _array_chunk_it multiple times, in an overlapping manner. Have multiple iterators running simultaneously. Plus it looks quite a bit nicer.) | [reply] [d/l] [select] |
|
|
this isn't something you should use recursion for
s/should/need to/
:) I meant should not, esp since there is nothing particularly recursive about it (you have to squint to make it recursive)
You also don’t need a module.
Sure I do :) otherwise I'm writing the the idiomatic perl solution
It was real hard to come up with
#!/usr/bin/perl --
use strict; use warnings;
my @x = ('a' .. 'z');
print yup( 5, @x ),"\n--\n";
print yup( 3, @x ),"\n";
sub yup {
my( $n, @x ) = @_;
my @yo;
for( my $ix = 0; $ix < @x; $ix += $n )
{
my $high = $n - 1 + $ix ;
$high > $#x and $high = $#x ;
push @yo, join ' ', @x[ $ix .. $high ];
}
return join ",\n", @yo;
}
__END__
a b c d e,
f g h i j,
k l m n o,
p q r s t,
u v w x y,
z
--
a b c,
d e f,
g h i,
j k l,
m n o,
p q r,
s t u,
v w x,
y z
| [reply] [d/l] |
Re: How to return a list using recursion?
by ig (Vicar) on Aug 07, 2012 at 06:11 UTC
|
sub _array_chunk5 {
my @arr = @_;
# Base case == when @arr is <= 5
return ( join( " ", @arr ) ) unless @arr > 5;
# what goes here ?
return ( join( " ", splice ( @arr, 0, 5 ) ) , _array_chunk5(@arr)
+ );
}
But I might write it more like:
sub _array_chunk5x {
my @arr = @_;
return ( ) if(@arr == 0);
return ( join( " ", splice( @arr, 0, 5 ) ), _array_chunk5(@arr) );
}
| [reply] [d/l] [select] |
Re: How to return a list using recursion?
by BillKSmith (Monsignor) on Aug 07, 2012 at 16:34 UTC
|
return (
join( ' ', splice(@arr, 0, 5)) . ",\n" ,
_array_chunk5(@arr),
);
Update: Sorry, I did not notice that this is the same as IG's solution. | [reply] [d/l] |