[SPOILER] Solution for Quiz of the Week #23 : parens
Kester Allen <[email protected]>
| Newsgroups | gmane.comp.lang.perl.qotw.discuss |
|---|---|
| Message-ID | <[email protected]> |
Here's my solution, woefully uncommented. I noticed that if you start
with the parentheses in this configuration (using n= as an example):
()()()() this could correspond to the binary number 10101010,
letting ( --> 1 and ) --> 0. The other end of the spectrum is:
(((()))) which corresponds to 11110000. You can think of these as a
power series in 2, with the ()()()() string being 2**1+2**3+2**5+2**7,
and the (((()))) string begin 2**7+2**6+2**5+2**4.
I kept track of the exponents of the power series (I called it a
two-power-series, or tps, in homage to Office Space), and it's fairly
easy to cycle through them.
The times I got for generating the output for n are:
n time(sec)
1 0
2 0
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
11 0
12 0
13 3
14 9
15 35
16 138
17 512
18 1914
and the code:
#!/usr/bin/perl
use warnings;
use strict;
{
my $n = shift () || 1;
my $do_all = shift ();
my $skip_print = shift ();
my @tps = start_tps ( $n );
while ( 1 ) {
print_parens ( @tps ) if ! $skip_print;
@tps = next_tps ( @tps );
if ( not defined $tps[0] ) {
last if not $do_all;
@tps = start_tps ( ++$n );
}
}
}
sub start_tps {
my ( $n ) = @_;
return map { (2 * $_)-1 } 1..$n;
}
sub next_tps {
my @tps = @_;
foreach ( 0 .. scalar @tps - 2 ) {
if ( $tps[$_] < $tps[$_+1] - 1 ) {
++$tps[$_];
@tps[0..$_-1] = start_tps ( $_ );
return @tps;
}
}
return undef;
}
sub print_parens {
my @tps = @_;
my @parens = map { '(' } 1 .. 2*(scalar @tps);
$parens[$_] = ')' foreach @tps;
printf "%d: %s\n", scalar @tps, join "", @parens;
}