CodeIQ:デスコロC #2

私自身が表題の問題を解いた時のプログラムについて解説します。
問題の詳細は「デスコロC #2」(CodeIQ)を参照してください。

問題の概要

問題を引用します。

aBcdEfGhijKlmnopQrStuvwxyzabCdefghijklmnOpqrstUvwxyzabcdefGhIjklmnOpqrStuvwxyzAbcdefghijKlmnopqrStuvWxyzabCdEfghijklmnopqrstuvWxyzabcdefghijklmnopqrStUvwxyzAbcdefghijKlmnopqrstuvWxYzabcdefghIjklmnOpQrstuvwxyzabCdefghijklmnopqrStUvwxyzabcdefGhijklmnopQrstuvWxyzabcdefghIjKlmnopQrstUvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijKlmnopqrStuvwxyzabCdEfghijklmnopqrstuvwxyzabcdefGhijklmnOpqrStuvwxYzabcdefghijKlmnopqrStuvWxyzabcdEfghijklmnOpqrstuvwxyzAbcdefghijklmnopqrstUvwxyzAbcdefghijKlmnopqrstuvWxYzabcdEfghijklmnOpqrstuvwxyzAbCdefghIjklmnopqrStUvwxyzabcdefghijklmnopQrstuvWxyzabcdefghIjKlmnopqrstuvwxyzAbcdefghijklmnOpqrstuvwxYzabcdefGhijklmnopQrstuvwxYzabcdefghijklmnopqrstuvWxyzabCdefGhijklmnOpqrstuvwxyzabcdefGhijklmnopQrstuvwxyzabCdEfghijklmnOpqrstUvWxyzabcdefghijklmnopqrstuvwxYzAbcdefghijklmnopqrStuvWxyzabCdefghijklmnopqrstuvWxyzAbcdefghIjklmnopqrStuvwxyzabcdEfghijKlmnopqrstuvwxyzabcdEfghIjklmnOpqrstuvwxyzabCdefghIjklmnopqrstUvwxyzabcdEfGhijklmnopqrstuvwxyzabcdefghIjKlmnopqrstUvwxyzabCdefghijklmnopqrstUvwxYzabcdEfghijklmnopQrstuvwxYzabcdefghijKlmnopqrstuvwxyzabcdefGhijklmnopqrstuvwxyzAbcdefghijKlmnopQrstuvwxyzabcdEfghijklmnopqrstUvwxyzabcdefGhijklmnopqrstuvwxyzAbcdefghijKlmnopqrstuvwxyzabCdEfghijklmnOpQrstuvWxyz

を標準出力してください。

私のプログラム

Pythonで解答しています。
2行目がはみ出しているのでスクロールしてください。

s=""
for i in range(1300):c=i%26+65;	s+=chr(c if c in b'BEGKQS,COU,GIOS,AKSW,CEW,SU,AKWY,IOQ,CSU,GQW,IKQU,,,,,KS,CE,GOSY,KSW, EO,AU,AKWY,EO,ACISU,QW,IK,AOY,GQY,W,CGO,GQ,CEOUW,Y,ASW,CW,AIS,EK,EIO,CIU,EG,IKU,CUY,EQY,K,G,AKQ,EU,G,AK,CEOQW'.split(b",")[i//26] else c+32)
print(s)

解説

この問題は解答するだけなら簡単です。単に、問題文の文字列を印字すればよいだけです。が、ショートコーディングの問題だったので少し努力して短くしています。トップレベルには全然かないませんが。

考え方

a-zを50回出力し、その中に時々大文字になっているものがあるという文字列を出力する必要があります。何か法則があるかと調べてはみましたが分からなかったので結果の文字列を圧縮することにしました。

「for i in range(1300)」のループは全体の文字数です。
次の「c=i%26+65」でA-Zの数値表現を作り、大文字にするべき文字なら大文字を返し、そうでなければ小文字を返すという条件文を書いています。

大文字かどうかを判断する部分が見にくいですが次のようになっています。
長いバイト列(b[BEGKQS,……,CEOQW])を,(コンマ)で分割し、リストを得ます。このバイト列は結果文字列から大文字になるものを26文字区切りで抜き出したものです。
そのリストの要素番号に「現在の文字番号//26」を指定するとリストの要素番号のバイナリ列が得られます。例えば現在の文字番号が0〜25なら[BEGKQS]です。
で、現在の文字がこの中に含まれているかどうかで判断します。

雑感

途中経過の集計(2016/2/22)を見ると最短のコードはPerlで49バイトです。これは私のような方法では到底無理に思えます。何か法則があるのでしょうか?