鈍足ランナーのIT日記

走るのが好きな5流のITエンジニアのブログ。

趣味の範囲は広いけど、どれも中途半端なクソブロガー楽しめるWebアプリを作ってあっと言わせたい。サーバーサイドPerl(Mojolicious)、クライアントサイドVue.js。Arduinoにも触手を伸ばす予定。

perlで解いた「積み木の水槽」

オフラインリアルタイムどう書く第13回の問題を解きました。 問題はこちら

うんうん、唸って考えて布団の中でも 色々考えて、半ば諦めかけてしまったけど。 すべて自力で解けた。すごく嬉しい。

同じ高さの積み木を1で積み木のないところを「0」で 表現して、それを正規表現で0をカウントしてやれば いいのではと閃いた。

「10+1」で正規表現で検索しにいくけれど、 カウントしたいのは0というところが すごく工夫したところ。正規表現の?の使い方 を知らなかったので、すごく勉強になった。

最後に、恒例のCMです。 IT系勉強会の検索に、dokechinの作った、ATNDフルカレンダーをよろしくお願いします。

package Water;
use strict;
use warnings;

sub getBitString {
    my $height = shift;
    if ( $height == 0 ) { return '00000000'; }
    if ( $height == 1 ) { return '10000000'; }
    if ( $height == 2 ) { return '11000000'; }
    if ( $height == 3 ) { return '11100000'; }
    if ( $height == 4 ) { return '11110000'; }
    if ( $height == 5 ) { return '11111000'; }
    if ( $height == 6 ) { return '11111100'; }
    if ( $height == 7 ) { return '11111110'; }
    if ( $height == 8 ) { return '11111111'; }

}

sub cal {
    my $heights = shift;
    my @mountain    = ();
    my $walls       = [];
    my $index       = 0;
    my $water       = 0;

    while ( length $heights > $index) {
        my $height = substr($heights,$index++,1);
        if ( $height == 0 && scalar($walls) > 0 ) {
            push( @mountain, $walls );
            $walls = [];
        }
        if ( $height > 0 ) {
            push( $walls, getBitString( $height - 1 ) );
        }
    }
    if ( scalar($walls) > 0 ) {
        push( @mountain, $walls );
    }

    foreach my $mountain (@mountain) {
        my $walls = $mountain;
        for my $i ( 0 .. 7 ) {
            my $str = "";
            foreach my $wall (@$walls) {
                $str = $str . substr( $wall, $i, 1 );
            }
            my $result = 0;
            while ( $str =~ /1(?=0+1)(0+)/g ) {
                $result =  $result + length $1;
            }
            printf "%d:%s,%d\n", $i, $str, $result;
            $water = $water + $result;
        }
        print "--------\n";
    }
    return $water;
}

1;