オフラインリアルタイムどう書く
- 第13回(9月6日) http://atnd.org/events/41603
の問題「積み木の水槽」
http://nabetani.sakura.ne.jp/hena/ord13blocktup/
の実装例。
他の言語などの解答例は
http://qiita.com/Nabetani/items/936e7885f4c607472060
から辿れます。
ちなみに次回は
- 第14回(9月28日) http://atnd.org/events/43076
です。
で。
//Groovy Version: 2.1.5 JVM: 1.7.0_07 Vendor: Oracle Corporation OS: Mac OS X
int solver( String src )
{
blocks = src.collect{ it.toInteger() }
(1..(blocks.size()-2)).sum{ ix ->
if ( ix<0 || blocks.size()<=ix || blocks[ix]==0 ){
return 0;
}
int left=0;
for( int i=ix-1 ; 0<blocks[i] && 0<=i ; --i ){
if ( left<blocks[i] ){
left = blocks[i]
}
}
int right=0
for( int i=ix+1 ; 0<blocks[i] && i<blocks.size ; ++i ){
if ( right<blocks[i] ){
right = blocks[i]
}
}
int height = Math.min( left, right )
Math.max( 0, height - blocks[ix] )
}
}
def test( src, expected )
{
String actual = solver( src ).toString();
println( [expected==actual ? "ok" : "***NG***", src, actual, expected ] )
}
/*2*/ test( "92308", "1" );
/*3*/ test( "90328", "1" );
/*0*/ test( "83141310145169154671122", "24" );
/*1*/ test( "923111128", "45" );
/*2*/ test( "923101128", "1" );
いつも通り、テストデータの大半は省略。
で。
その場で書いたもの。
なんかつまんないバグ(詳細失念)に引っかかって時間がかかってしまい、ソースが整理できていない。
方針は:
- 左から順に調べる。
- 自分より左にあって「0の列又は左端」まで調べて、最大値(
left
)を得る。 - 自分より右にあって「0の列又は右端」まで調べて、最大値(
right
)を得る。 -
left
とright
の小さいほうが水面の高さ。 - 自分の場所を引くと水の量になるけど、マイナスにならないように手を加える
- というような値の総和を取る
というもの。関数が長すぎるし、重複もあるのでリファクタリングするべきだと思う。ix ->
などとせずに it
がいいとか、この for文はないだろうとか、いろいろ。
苦し紛れに C言語のような for 文を書いてしまったが、こういうループの時 groovy では普通どうするんだろう。