第16回オフラインリアルタイムどう書くの問題をPythonで解いてみた

問題はこちら。 http://nabetani.sakura.ne.jp/hena/ord16boseg/
時間がなくて、横方向と縦方向の冗長な処理をまとめるとこまでできませんでした。
後ほど整理しようと思います。

整理後: ビットマップ演算を使うようにしたsolve関数。

```py
def solve(data):
  h=[int(data[i:i+2],8) for i in range(0,len(data),2)]
  v=[int(''.join(y),2) for y in zip(*[format(x,'06b') for x in h])]
  c=sum(map(len,format(m[y]^m[y+1],'b').split('0')) for y in range(0,5) for m in(h,v),[])
  return ','.join(map(str,[sum(c,[]).count(i) for i in range(1,7)]))
```

解説:

```py
#ビットマップ作成: 8進数文字列を2文字ずつ切り出し、数値配列にする
h=[int(data[i:i+2],8) for i in range(0,len(data),2)]
  for i in range(0,len(data),2) #2文字ずつ切り出すためのインデックス番号生成
  data[i:i+2]                   #2文字ずつ取り出す
  int(... ,8)                   #8進数文字列を数値化
  [...]                         #配列にする

#縦横置換ビットマップ作成: 二進数文字列配列にして縦横置換してから再び数値配列に
v=[int(''.join(y),2) for y in zip(*[format(x,'06b') for x in h])]
  [format(x,'06b') for x in h] #数値配列を2進数6桁文字列の配列にし
  zip(*[...])                  #配列要素を引数展開(*)してzipして1文字毎に縦横置換
  for y in zip(...)            #配列要素('0'か'1'が6個の配列)について
  ''.join(...)                 #1文字毎になった2進数文字を連結して2進数文字列化
  int(... ,2)                  #2進数文字列を数値化
  [...]                        #配列にする


#各行間のビットマップのXORをとり、1のビットが連続する長さを配列にする
c=[map(len,format(m[y]^m[y+1],'b').split('0')) for y in range(0,5) for m in(h,v)]
  for m in(h,v)          #横方向と縦方向のビットマップに対して
  for y in range(0,5)    #y=0～4, 0-1,1-2,2-3,3-4,4-5行間のXORをとるために
  m[y]^m[y+1]            #行間のXORをとって境界線部分のビットを1に
  format(... ,'b')       #ビット列数値を2進数文字列に
  .split('0')            #'0'で分断し、'1'の連続要素を作る
  map(len, ...)          #'1'の長さの配列を作る
  [...]                  #配列にする(配列の配列、2次元配列になる)


#長さの配列から、長さごとの出現数を数え、','で区切った文字列を返す
return ','.join(map(str,[sum(c,[]).count(i) for i in range(1,7)]))
  for i in range(1,7)    #1～6の長さについて
  sum(c,[])              #2次元配列のcをフラット化し、1次元配列にしてから
  .count(i)              #長さの出現数を数え
  [...]                  #配列にする
  map(str, ...)          #1～6の出現数を文字列の配列にする
  ','.join(...)          #出現数文字列配列を','で接続した文字列にして
  return ...             #返す
```

整理前: 会場で1時間で書いたソース

```py
#!/usr/bin/env python
#-*- coding:utf-8 -*-

def solve(data):
    data += "00"
    m = [format(int(data[i:i+2],8), "06b")+"0" for i in xrange(0,len(data),2)]
    count = [0]*7
    for x in xrange(0,5):
        n = 0
        last=(0,0)
        for y in xrange(0,7):
            z = (m[y][x], m[y][x+1])
            if z != last:
                count[n] += 1
                n = 0
            if z[0] != z[1]: n += 1
            last = z
    for y in xrange(0,5):
        n = 0
        last=(0,0)
        for x in xrange(0,7):
            z = (m[y][x], m[y+1][x])
            if z != last:
                count[n] += 1
                n = 0
            if z[0] != z[1]: n += 1
            last = z
    return ','.join(map(str,count[1:]))

def test(data, correct):
    answer = solve(data)
    print "OK" if answer==correct else "NG", answer, correct, data

if __name__ == '__main__':
    0, test( "060276724276", "6,2,1,1,0,1" );
    1, test( "770175454177", "2,3,0,3,1,0" );    
    2, test( "743733377170", "9,3,1,0,0,0" );    
    3, test( "724212121273", "5,2,1,1,1,1" );    
    4, test( "100000000000", "3,0,0,0,0,0" );    
    5, test( "000002000000", "4,0,0,0,0,0" );    
    6, test( "003622223600", "0,4,0,4,0,0" );    
    7, test( "520073737070", "8,3,1,1,0,0" );    
    8, test( "770077007700", "0,0,0,0,0,5" );    
    9, test( "555555555514", "2,0,0,0,2,2" );    
    10, test( "764252427600", "4,0,4,0,2,0" );    
    11, test( "774555554177", "3,3,1,3,0,0" );    
    12, test( "674574754557", "11,5,0,1,0,0" );    
    13, test( "000000000000", "0,0,0,0,0,0" );    
    14, test( "777777777777", "0,0,0,0,0,0" );    
    15, test( "774377777577", "6,0,2,0,0,0" );    
    16, test( "070777777777", "0,1,1,0,0,0" );    
    17, test( "373737373737", "0,0,0,0,0,1" );    
    18, test( "603260327725", "30,0,0,0,0,0" );    
    19, test( "466331144663", "30,0,0,0,0,0" );    
    20, test( "000000000242", "3,2,0,0,0,0" );    
    21, test( "567656043772", "18,2,1,0,0,0" );    
    22, test( "200763012420", "15,4,1,0,0,0" );    
    23, test( "400101140052", "14,3,0,0,0,0" );    
    24, test( "764767476476", "13,2,0,1,0,0" );    
    25, test( "001110140110", "12,2,1,0,0,0" );    
    26, test( "765405076527", "16,3,0,1,0,0" );    
    27, test( "377323370373", "8,4,2,0,0,0" );    
    28, test( "250541131216", "11,5,2,0,0,0" );    
    29, test( "744165741476", "12,3,2,0,0,0" );    
    30, test( "042101000300", "10,3,0,0,0,0" );    
    31, test( "002004554101", "11,3,1,0,0,0" );    
    32, test( "371707762706", "15,1,1,0,0,0" );    
    33, test( "130371310175", "7,3,1,2,0,0" );    
    34, test( "212537003613", "13,2,1,1,1,0" );    
    35, test( "157700063411", "15,3,0,0,0,1" );    
    36, test( "011500036007", "6,7,1,0,0,0" );    
    37, test( "743113313517", "17,2,1,0,0,0" );    
    38, test( "174105270405", "13,3,1,1,0,0" );    
    39, test( "427272200311", "13,3,2,0,0,0" );    
    40, test( "725370332237", "12,5,1,1,0,0" );    
    41, test( "005640420046", "12,1,3,0,0,0" );    
    42, test( "700350001101", "14,3,1,0,0,0" );    
    43, test( "577627744076", "16,1,1,1,0,0" );    
    44, test( "620332232007", "10,4,2,1,0,0" );    
    45, test( "260406401000", "15,1,1,0,0,0" );    
    46, test( "737272723276", "5,0,0,0,3,0" );    
    47, test( "000400040444", "7,0,2,0,0,0" );    
    48, test( "370222002177", "13,2,2,0,0,0" );    
    49, test( "372236024656", "9,3,2,0,1,0" );    
    50, test( "276131137003", "11,6,2,0,0,0" );    
    51, test( "742134007240", "13,4,2,0,0,0" );    
    52, test( "777721775571", "13,1,2,0,0,0" );    
    53, test( "700301232233", "11,2,3,0,0,0" );
```