Re: [SPOILER] Solution for Quiz of the Week #23 : parens

Zed Lopez <[email protected]>
Newsgroups gmane.comp.lang.perl.qotw.discuss
Message-ID <[email protected]>
Here's my fast, but hard to read, version:

#!/usr/bin/perl
use strict;

my $n = shift;
die "Usage: $0 n [where n is a positive integer]" unless defined $n
and $n !~ /\D/;
exit unless $n;
print "()\n" and exit if $n == 1;

my (@parens, @right, @left);
@right = (')') x (2*$n-2);
@left = ('(') x (2*$n-2);
my $limit = 3; 
my @code = ('for my $v1 (0..1) {');
for (2..$n-1) {
    push @code, "for my \$v$_ (\$v" . ($_-1) . "+1..$limit) {";
    $limit += 2;
}
push @code, '@parens = @right; @parens[', (join ',', map "\$v$_", (1..$n-1)), 
    '] = @left; print join "", "(", @parens, ")\n"', '}' x ($n-1);
eval join '', @code;

Here's another with the same basic algorithm, but using
Algorithm::Loops to build the loops, instead of self-generated
code. It's slower, but pretty much as hard to read.

#!/usr/bin/perl
use strict;
use warnings;
use Algorithm::Loops qw( NestedLoops );

my $n = shift;
die "Usage: $0 n [where n is a positive integer]" unless defined $n
and $n !~ /\D/;
exit unless $n;
print "()\n" and exit if $n == 1;

sub create_iterator_closure {
   my $p = $_[0]*2-1;
   return sub { [ $_+1..$p ] };
}

my (@parens, @right, @left);
@right = (')') x (2*$n-2);
@left = ('(') x (2*$n-2);

my $loop = [[0..1]];
push(@$loop, create_iterator_closure($_)) for (2..$n-1);
my $iter = NestedLoops($loop);
while (my @list = $iter->()) {
    @parens = @right;
    @parens[@list] = @left;
    print join '', '(', @parens, ')', "\n";
}

I solicited and received help getting the NestedLoops
parameter right at Perlmonks (thanks to ikegami, who supplied
the create_iterator_closure routine as it appears here.) I considered
trying to change the values in my question so it wouldn't act as a
spoiler for any qotw participants reading Perlmonks. I decided the
relationship between my question and the quiz was obscure enough
already.

http://www.perlmonks.org/index.pl?node_id=387799

I spent some of this afternoon at the UC Berkeley Math Library looking
at combinatorics textbooks trying to see if the matherati offered some
clever solution to this. I didn't find one. All those combinatorial
mathematicians want to do is to _avoid_ enumerating sequences by
coming up with clever ways to generate their counts. (It is pretty
astonishing how many problems this is equivalent to, though.)

There's a really interesting pattern lurking in the relationship
between these strings evaluated as binary numbers, but I haven't quite
cracked it. I really hope someone else's solution depends on it.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.