diff options
| author | Bob Lied <boblied+github@gmail.com> | 2025-11-09 10:21:37 -0600 |
|---|---|---|
| committer | Bob Lied <boblied+github@gmail.com> | 2025-11-09 10:21:37 -0600 |
| commit | 5454c1a8f17e4143bbc8a7c84938b7974580fc10 (patch) | |
| tree | 2f068f9fc0afb633041e548d86aeff0ec407944e | |
| parent | 63a175f357a49fd05553b3f37e6d1ff506e74b4a (diff) | |
| download | perlweeklychallenge-club-5454c1a8f17e4143bbc8a7c84938b7974580fc10.tar.gz perlweeklychallenge-club-5454c1a8f17e4143bbc8a7c84938b7974580fc10.tar.bz2 perlweeklychallenge-club-5454c1a8f17e4143bbc8a7c84938b7974580fc10.zip | |
Week 346 solutions
| -rw-r--r-- | challenge-346/bob-lied/perl/ch-1.pl | 19 | ||||
| -rw-r--r-- | challenge-346/bob-lied/perl/ch-2.pl | 68 |
2 files changed, 67 insertions, 20 deletions
diff --git a/challenge-346/bob-lied/perl/ch-1.pl b/challenge-346/bob-lied/perl/ch-1.pl index f84a011408..0daafd4dbf 100644 --- a/challenge-346/bob-lied/perl/ch-1.pl +++ b/challenge-346/bob-lied/perl/ch-1.pl @@ -50,33 +50,40 @@ say longestParen($_) for @ARGV; #============================================================================= sub longestParenSub($str) { + # Since the ony characters are ( and ), if there are any balanced + # sets at all, at some point there must be a (). Replace those with + # something else (I'm using xx). Then keep replacing matching pairs + # of parenthese as long as we have (xxxxxx) patterns. while ( $str =~ s/\((x*)\)/x$1x/g ) { } + # Extract the strings of x, map to length, and find the longest one. use List::Util qw/max/; return ( max map { length($_) } $str =~ m/x+/g ) // 0; } sub longestParen($str) { + # Leading ) and trailing ( can never pair up, so a small + # optimization is to trim those off before we start. + $str =~ s/^\)+//; + $str =~ s/\($//; + + # Stack up when we hit a (, pop off when we find a ). my @stack = ( -1 ); my $longest = my $streak = 0; - my $open = 0; for my ($i, $p) ( indexed split(//, $str) ) { if ( $p eq '(' ) { - push @stack, $i; + push @stack, $i; # Note, pushing index } else { pop @stack; if ( @stack ) { my $len = $i - $stack[-1]; + $logger->debug(") i=$i len=$len stack=(@stack)"); $longest = $len if $len > $longest; } - else - { - push @stack, $i; - } } $logger->debug("$p i=$i, longest=$longest, stack=(@stack)"); } diff --git a/challenge-346/bob-lied/perl/ch-2.pl b/challenge-346/bob-lied/perl/ch-2.pl index 47abbaa0c6..ee93a1f817 100644 --- a/challenge-346/bob-lied/perl/ch-2.pl +++ b/challenge-346/bob-lied/perl/ch-2.pl @@ -21,14 +21,14 @@ #============================================================================= use v5.42; +use feature "class"; no warnings "experimental::class"; use Getopt::Long; my $Verbose = false; my $DoTest = false; -my $Benchmark = 0; -GetOptions("test" => \$DoTest, "verbose" => \$Verbose, "benchmark:i" => \$Benchmark); +GetOptions("test" => \$DoTest, "verbose" => \$Verbose); my $logger; { use Log::Log4perl qw(:easy); @@ -37,9 +37,39 @@ my $logger; $logger = Log::Log4perl->get_logger(); } #============================================================================= +# Iterator to do permutations by counting. If there are 'base' objects, count +# in base 'base'. Take it up to 'n' choices, then return undef to signal +# the end. +class Permute { + field $base :param //= 4; + field $n :param //= 3; + field $max = $base ** ($n); + + field @c = (0) x $n; + field $count = 0; + field $number = 0; + + method next() + { + return undef if ++$number >= $max; + + my $place = 0; + my $carry; + while ( ($carry = (++$c[$place] % $base)) == 0 ) + { + $c[$place++] = 0; + } + return $self; + } + + # Return the selections as reference to array. + method val() { return $number < $max ? \@c : undef } + + method show() { "(" . join(" ", reverse(@c)) . ")" } +}; +#============================================================================= exit(!runTest()) if $DoTest; -exit( runBenchmark($Benchmark) ) if $Benchmark; say '(', join(', ', magic(@ARGV)->@*), ')'; @@ -48,8 +78,28 @@ sub magic($str, $target) { state @OP = ("", "-", "+", "*"); $logger->debug("@OP"); + + my @s = split(//, $str); my @expr; - return \@expr; + + my $count = Permute->new( base => scalar(@OP), n => $#s ); + + for ( ; my $idx = $count->val ; $count->next ) + { + my @ops = ( ( map { $OP[$_] } $count->val()->@*), ""); + + use List::Util qw/mesh/; + my $e = join("", mesh \@s, \@ops); + + # Numbers with leading zeroes don't count + next if $e =~ m/^0\d|[^0-9]0\d/; + + my $t = eval $e; + $logger->debug("ops:", $count->show(), " |", join("|", @ops), '|', "expr: ", $e, "=$t"); + push @expr, $e if $t == $target; + } + + return [sort @expr]; } sub runTest @@ -64,13 +114,3 @@ sub runTest done_testing; } - -sub runBenchmark($repeat) -{ - use Benchmark qw/cmpthese/; - - cmpthese($repeat, { - label => sub { }, - }); -} - |
