aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-214/james-smith/perl/ch-2.pl64
1 files changed, 63 insertions, 1 deletions
diff --git a/challenge-214/james-smith/perl/ch-2.pl b/challenge-214/james-smith/perl/ch-2.pl
index 275e2aff92..1cd0bfdb3d 100644
--- a/challenge-214/james-smith/perl/ch-2.pl
+++ b/challenge-214/james-smith/perl/ch-2.pl
@@ -13,6 +13,8 @@ my @TESTS = (
[ [2,1,2,1,2,1,2,1,2,1,2,1,2,1,2], 1 ],
);
+my($cache,$m);
+
sub collect {
return 0 unless @_;
my $m = 0;
@@ -28,5 +30,65 @@ sub collect {
$m
}
-is( collect( @{$_->[0]} ), $_->[1] ) for @TESTS;
+sub collect_cache {
+ return 0 unless @_;
+ my $k = "@_";
+ return $cache->{$k} if exists $cache->{$k};
+ my $m = 0;
+ for ( my $e = my $o=0; $o<@_; ) {
+ my $e = $o;
+ $e++ while $_[$o]==$_[$e];
+ my $s = ($e-$o)**2 + collect_cache( @_[ 0..$o-1, $e..$#_ ] );
+ $m = $s if $s > $m;
+ $o = $e;
+ }
+ $cache->{$k} = $m;
+}
+
+sub _collect_fast {
+ my $s = shift;
+ return $s unless @_; ## Empty list return score
+
+ ## same digits.
+ for ( my $e = my $o = 0; $o<@_; ) { ## We loop through
+ my $e = $o; ## the list for each
+ $e++ while $_[$o]==$_[$e]; ## sequence of same no.
+
+ ## Compute the score so far $s + length of seq^2
+ ## Compute max poss. score this + sum of squared
+ ## counts of other number frequencies
+
+ my $ms = my $ts = $s + ($e-$o)**2;
+ my %f = ($_[$o] => $o-$e);
+ $f{$_}++ for @_;
+ $ms += $_ ** 2 for values %f;
+
+ ## If the max possible score is > $m we compute
+ ## actual score and update max if > $m
+
+ if($ms>$m) {
+ $ts = _collect_fast( $ts, @_[ 0..$o-1, $e..$#_ ] );
+ ## And if it is greater than $m we update $m
+ $m = $ts if $ts > $m;
+ }
+ $o = $e;
+ }
+}
+
+sub collect_fast {
+ return 0 unless @_;
+ my %f;
+ $m=0;
+ $f{$_}++ for @_; ## compute freq
+ $_>$m && ( $m=$_ ) for values %f; ## find largest
+ $m = $m*$m + @_-$m; ## Compute minimum-maximum
+ ## square of max freq -
+ ## count of remaining
+ _collect_fast(0,@_); ## Now do the real work
+ $m ## Return max (global variable)
+}
+
+ is( collect( @{$_->[0]} ), $_->[1] ) for @TESTS;
+ is( collect_fast( @{$_->[0]} ), $_->[1] ) for @TESTS;
+$cache={},is( collect_cache( @{$_->[0]} ), $_->[1] ) for @TESTS;
done_testing();