また星田さんのブログを眺めていたら人気記事で過去のプログラミング記事があがっていた。
何か最近人気ある(笑)?
問題は以下の通り。
とまぁこんなカンジだ。
さて、これは圧縮がトピックなんだけど、基本はいつぞや書いた「ランレングス圧縮」だ。
ロジック自体はそっちの記事に書いてるんで端折るとして。
Pythonなら単純にはitertools.groupbyを使えばいい。これは基本的にはランレングス圧縮のアルゴリズムが仕込んである。
例えば、文字列"bbbwwwww"と"wwwwwbbb"に対して、
と言う結果が返ってくる。
残念ながら返却リストの要素であるタプルの第2要素がイテラブルなんでちとメンド臭いんだけど、ここをリスト化すれば回収した要素が入っている。
と言うわけで、基本戦略的には次のように書く。
def foo(line):
from itertools import groupby
return " ".join([str(len(list(g))) for k, g in groupby(line)])
受け取った文字列をgroupbyでランレングス圧縮にかける。
結果は2要素のタプルで、集めた情報(イテラブル)はgになるんでそいつをリストに変換、そして長さを調べてその結果を文字列にする。
全般的にはリスト内包表記によりリストになるんで、それを文字列にするわけだ。
ただし、受け取った文字列の先頭がwの時にはアタマに0を付け足したい。
従って関数fooを次のように改造する。
def foo(line):
from itertools import groupby
return "{}{}".format("" if line[0] == 'b' else '0 '," ".join([str(len(list(g))) for k, g in groupby(line)]))
結果はこんなカンジだ。
ここまで書ければあとはオシマイ、ってなカンジだ。
ロジックサマナーでの件の問題の解は以下のようになるだろう。
input_line = input().rstrip()
def foo(line):
from itertools import groupby
return "{}{}".format("" if line[0] == 'b' else '0 ',
" ".join([str(len(list(g))) for k, g in groupby(line)]))
print(foo(input_line))
これで終わり、だ。
お疲れ様。