package Max_score_subs; use strict; use warnings; use feature 'say'; use PDL; use Exporter 'import'; our %EXPORT_TAGS = ( all => [ qw/ mscore_perl mscore_pdl mscore_c mscore_c_better mscore_c2f mscore_f /], ); Exporter::export_ok_tags( 'all' ); sub mscore_perl { my $s = shift; my $max = '0' eq substr $s, 0, 1; $s = substr $s, 1; $max += $s =~ tr/1//; chop $s; my $score = $max; while ( $s =~ /(0*)(1*)/g ) { $score += length $1; $max = $score if $score > $max; $score -= length $2 } return $max } sub mscore_pdl { my $s = shift; my $count = $s =~ tr/1//; chop $s; $s =~ tr/01/\xff\1/; my $p = zeroes sbyte, length $s; ${ $p-> get_dataref } = $s; $p-> upd_data; $count - $p-> cumusumover -> minover -> sclr } use FindBin; use Inline Config => force_build => 1; use Inline C => Config => libs => "-L$FindBin::Bin -lmscore_f -lgfortran -lquadmath"; use Inline C => << 'END_OF_C'; extern void c2f_( void* n, void* s, void* ret ); extern void f_( void* n, void* s, void* ret ); int mscore_c( SV* str ) { int i, acc, score, max, one; STRLEN len; char* buf = SvPV( str, len ); len --; acc = 0; score = 0; max = -1; for( i = 0; i < len; i ++ ) { one = buf[ i ] - '0'; acc += one; score += one ? -1 : 1; max = score > max ? score : max; } return max + acc + ( buf[ i ] == '1' ); } int mscore_c_better( SV* str ) { int i, acc, tmp, max; STRLEN len; char* buf = SvPVbyte( str, len ); len --; acc = 0; max = -2; for( i = 0; i < len; i ++ ) { acc += buf[ i ] - '0'; tmp = i - 2 * acc; max = tmp > max ? tmp : max; } return max + acc + ( buf[ len ] == '1' ) + 1; } int mscore_c2f( SV* str ) { STRLEN len; char* buf = SvPVbyte( str, len ); int ret; c2f_( &len, buf, &ret ); return ret; } int mscore_f( SV* str ) { STRLEN len; char* buf = SvPVbyte( str, len ); int ret; f_( &len, buf, &ret ); return ret; } END_OF_C 1;