Problem:
Falling Block Puzzle
ブロック落とし
あなたはある落ち物パズルで遊んでいる．
このパズルのフィールドは，下図のように各段に立方体のセルが2マス×2マスに並び，段が上に無限に並んでいる形をしている．
それぞれのセルは，セルにぴったり収まるブロックが1つ存在するか，何もないかのどちらかである．
このパズルは以下のように進行する．
初期状態としていくつかのブロックが設置されている．
2マス×2マス×2マスに収まるブロックの塊を上から落とす．ただし，落とす前に，ブロックがフィールドからはみ出さないようにして塊を水平方向に平行移動することができる．
落としたブロックのうち，ある1つの下面が，すでに置かれているブロックまたはフィールドの底に着いた時点で，すべてのブロックの落下が止まり停止する．
それぞれの段について，4マス全てが埋まっていればその段のブロックは消滅し，その上にあるブロックが1段ずつ落下する．落下後のそれぞれのブロックの下のセルにブロックがなかったとしても，それ以上落下することはない．
2に戻る．
初期状態で置かれているブロックと，落とす塊がいくつか与えられるので，与えられる順に全ての塊を落とすことで，最大いくつの段を消すことができるかを求めるプログラムを作れ．
Input
入力は100個以下のデータセットからなる．各データセットは以下の形をしている．
(初期状態のブロックの高さ
H
) (落とす塊の数
N
)
(初期状態の1段目)
...
(初期状態の
H
段目)
(1個目の落とす塊)
...
(
N
個目の落とす塊)
各データセットの1行目には初期状態のブロックの高さ
H
(1 ≤
H
≤ 10)と落とす塊の数
N
(1 ≤
N
≤ 3)が指定されている．
続いて初期状態のそれぞれ段の情報が以下の形式で与えられる．
c
11
c
12
c
21
c
22
c
ij
はそれぞれのセルの情報を表し，'
#
'はブロックが存在することを，'
.
'はブロックがないことを表す．1段目から
H
段目までのそれぞれの段について，全てのセルにブロックが存在したり，全てのセルにブロックがなかったりすることはないと仮定して良い．
続いてそれぞれの落とす塊の情報が以下の形式で与えられる．
b
111
b
112
b
121
b
122
b
211
b
212
b
221
b
222
初期状態の形式と同様に'
#
'はブロックが存在することを，'
.
'はブロックがないことを表す．それぞれの塊には少なくとも1つのブロックが含まれる．塊に含まれるブロックは角や辺のみで接していることがあり，面で繋がっているとは限らない．
初期状態・ブロックの塊の入力の添え字の対応は以下の図を参照すること．
入力の終わりは，2つのゼロからなる1行で示される．
なお，下図は，後に示す Sample Input 中の最初のデータセットを表している．このデータセットでは，ブロックの塊を斜めに平行移動した後に落下させることで1つの段を消すことができる．
Output
各データセットに対して，最大でいくつの段を消すことができるかを1行に出力せよ．
Sample Input
1 1
##
#.
..
..
#.
..
1 1
.#
#.
#.
..
..
.#
2 2
##
#.
##
#.
..
.#
##
#.
#.
..
#.
..
1 3
#.
..
##
##
##
##
##
##
##
##
##
##
##
##
10 3
##
#.
##
#.
##
.#
##
.#
#.
##
#.
##
.#
##
.#
##
.#
#.
.#
#.
#.
.#
#.
.#
#.
..
#.
..
#.
..
#.
..
10 3
##
.#
##
..
##
#.
.#
..
##
.#
.#
##
.#
##
#.
##
##
.#
..
.#
#.
#.
.#
#.
#.
#.
#.
..
..
..
..
.#
0 0
Output for Sample Input
1
0
3
6
6
0

Submitted solutions:

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
#define rep(i,n) for(ll i=0;i<ll(n);i++)
#define all(A) A.begin(),A.end()

void chmax(ll& p, ll q) { p = max(p, q); };
void chmin(ll& p, ll q) { p = min(p, q); };

void solve(ll H, ll N) {
    vvvll BB(H + 2 * N + 5, vvll(2, vll(2, 0)));
    rep(h, 2)rep(i, 2)rep(j, 2)BB[h][i][j] = 6;
    ll an = 0;
    rep(h, H)rep(i, 2) {
        string S;
        cin >> S;
        rep(j, 2)if (S[j] == '#')BB[h + 2][i][j] = 1;
    }
    vector<vvvll> G(N, vvvll(2, vvll(2, vll(2, 0))));
    rep(n, N)rep(h, 2)rep(i, 2) {
        string S;
        cin >> S;
        rep(j, 2)if (S[j] == '#')G[n][h][i][j] = 1;
    }
    rep(bit, 9 * 9 * 9) {
        ll res = 0;
        bool PUT = 1;
        ll nbit = bit;
        auto B = BB;
        rep(n, N) {
            ll dx = nbit % 3 - 1;
            nbit /= 3;
            ll dy = nbit % 3 - 1;
            nbit /= 3;
            vvvll C(2, vvll(2, vll(2, 0)));
            rep(h, 2)rep(i, 2)rep(j, 2) {
                if (i + dx >= 0 && j + dy >= 0 && i + dx < 2 && j + dy < 2)C[h][i][j] = G[n][h][i + dx][j + dy];
            }
            rep(h, 2) {
                ll cnt = 0;
                rep(i, 2)rep(j, 2)cnt += G[n][h][i][j] - C[h][i][j];
                if (cnt != 0)PUT = 0;
            }
            if (!PUT)break;

            ll pt = -1;
            for (ll K = H + N * 2 + 1; K >= 0; K--) {
                bool OK = 1;
                rep(h, 2)rep(i, 2)rep(j, 2) {
                    if (min(C[h][i][j], B[K + h][i][j]) >= 1)OK = 0;
                }
                if (!OK) {
                    pt = K + 1;
                    break;
                }
            }
            rep(h, 2)rep(i, 2)rep(j, 2) {
                B[pt + h][i][j] += C[h][i][j];
            }
            ll cnt = 0;
            rep(i, 2)rep(j, 2)cnt += B[pt + 1][i][j];
            if (cnt == 4) {
                res++;
                rep(i, 2)rep(j, 2)B[pt + 1][i][j] = 0;
            }
            cnt = 0;
            rep(i, 2)rep(j, 2)cnt += B[pt][i][j];
            if (cnt == 4) {
                res++;
                rep(i, 2)rep(j, 2) {
                    B[pt][i][j] = B[pt + 1][i][j];
                }
            }
        }
        chmax(an, res);
    }

    cout << an << endl;
}

int main() {

    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    ll H, N;
    while (cin >> H >> N) {
        if (H + N == 0)return 0;
        solve(H, N);
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3372
final_rank: 15

code_snippet: #include<bits/stdc++.h>
using namespace std;

bool is_end = false;

using ARR = array<array<char, 2>, 2>;
const ARR EMPTY = {array<char, 2>{'.', '.'}, array<char, 2>{'.', '.'}};
const array<ARR, 2> EMPTYCUBE = {EMPTY, EMPTY};

void solve() {
  int H, N;
  cin >> H >> N;

  if(H == 0 && N == 0) {
    is_end = true;
    return;
  }

  vector<ARR> field_init;
  for(int i = 0; i < H; i++) {
    ARR c;
    string s;
    cin >> s;
    c[0][0] = s[0], c[0][1] = s[1];
    cin >> s;
    c[1][0] = s[0], c[1][1] = s[1];
    field_init.push_back(c);
  }

  vector<array<ARR, 2>> b(3, EMPTYCUBE);
  for(int i = 0; i < N; i++) {
    string s;
    cin >> s;
    b[i][0][0][0] = s[0], b[i][0][0][1]  = s[1];
    cin >> s;
    b[i][0][1][0] = s[0], b[i][0][1][1]  = s[1];
    cin >> s;
    b[i][1][0][0] = s[0], b[i][1][0][1]  = s[1];
    cin >> s;
    b[i][1][1][0] = s[0], b[i][1][1][1]  = s[1];
    if(b[i][0] == EMPTY) swap(b[i][0], b[i][1]);
  }

  int ans = 0;
  for(int ax : {-1, 0, 1}) for(int ay : {-1, 0, 1}) {
    for(int bx : {-1, 0, 1}) for(int by : {-1, 0, 1}) {
      for(int cx : {-1, 0, 1}) for(int cy : {-1, 0, 1}) {

        int cnt_del = 0;
        bool valid = true;
        vector<ARR> field = field_init;

        auto is_adj = [&](int pos, array<ARR, 2> block) -> bool {
          for(int j = 0; j < 1 << 2; j++) {
            int j0 = (j >> 0) & 1;
            int j1 = (j >> 1) & 1;
            if(block[0][j0][j1] == '#') {
              if(field[pos][j0][j1] == '#') return true;
            }else if(block[1][j0][j1] == '#') {
              if(field[pos + 1][j0][j1] == '#') return true;
            }
          }
          return false;
        };

        auto stopper = [&](array<ARR, 2> block) -> int {
          field.push_back(EMPTY);
          field.push_back(EMPTY);
          for(int i = int(field.size()) - 3; i >= 0; i--) {
            if(is_adj(i, block)) {
              return i + 1;
            }
          }
          return 0;
        };

        auto place = [&](array<ARR, 2> block) -> void {
          int stp = stopper(block);
          if(stp >= int(field.size())) {
            field.push_back(block[0]);
          }else {
            if(block[0][0][0] == '#') field[stp][0][0] = block[0][0][0];
            if(block[0][0][1] == '#') field[stp][0][1] = block[0][0][1];
            if(block[0][1][0] == '#') field[stp][1][0] = block[0][1][0];
            if(block[0][1][1] == '#') field[stp][1][1] = block[0][1][1];
          }
          stp++;
          if(stp >= int(field.size())) {
            field.push_back(block[1]);
          }else {
            if(block[1][0][0] == '#') field[stp][0][0] = block[1][0][0];
            if(block[1][0][1] == '#') field[stp][0][1] = block[1][0][1];
            if(block[1][1][0] == '#') field[stp][1][0] = block[1][1][0];
            if(block[1][1][1] == '#') field[stp][1][1] = block[1][1][1];
          }
          vector<ARR> field_new;
          for(int i = 0; i < int(field.size()); i++) {
            if(field[i][0][0] == '.') { field_new.push_back(field[i]); continue; }
            if(field[i][0][1] == '.') { field_new.push_back(field[i]); continue; }
            if(field[i][1][0] == '.') { field_new.push_back(field[i]); continue; }
            if(field[i][1][1] == '.') { field_new.push_back(field[i]); continue; }
            cnt_del++;
          }
          swap(field, field_new);
        };

        auto moved = [&](array<ARR, 2> block, int dx, int dy) -> array<ARR, 2> {
          array<ARR, 2> ret = EMPTYCUBE;
          for(int j = 0; j < 1 << 3; j++) {
            int j0 = (j >> 0) & 1;
            int j1 = (j >> 1) & 1;
            int j2 = (j >> 2) & 1;
            if(block[j0][j1][j2] == '.') continue;
            if(j1 + dx < 0 || j1 + dx > 1) { valid = false; continue; }
            if(j2 + dy < 0 || j2 + dy > 1) { valid = false; continue; }
            ret[j0][j1 + dx][j2 + dy] = block[j0][j1][j2];
          };
          return ret;
        };

        place(moved(b[0], ax, ay));
        // if(ax == 0 && ay == 0 && bx == 1 && by == 1 && cx == 0 && cy == 0) {
        //   for(auto fi : field) {
        //     cout << fi[0][0] << fi[0][1] << endl;
        //     cout << fi[1][0] << fi[1][1] << endl;
        //     cout << endl;
        //   }
        // }

        place(moved(b[1], bx, by));
        place(moved(b[2], cx, cy));
        if(valid) ans = max(ans, cnt_del);
      }
    }
  }
  cout << ans << endl;
}

int main() {
  while(!is_end) { solve(); }
}
accuracy: 1
time_ms: 30
memory_kb: 3340
final_rank: 10

code_snippet: #include<bits/stdc++.h>

using namespace std;

using ll=long long;


int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while(1){
        int h, n;
        cin >> h >> n;
        if(h==0 and n==0)break;
        h = h + 10;
        vector st(4, vector<int>(h));
        for (int x = 0; x < h - 10; ++x) {
            for (int i = 0; i < 2; ++i) {
                string s;
                cin >> s;
                for (int j = 0; j < 2; ++j) {
                    if (s[j] == '#')st[i * 2 + j][x] = 1;
                    else st[i * 2 + j][x] = 0;
                }
            }
        }
        auto ch = [&](int H) {
            int cnt = 0;
            if(H>=st[0].size())return false;
            if(H<0)return false;
            for (int pos = 0; pos < 4; ++pos) {
                cnt += st[pos][H];
            }
            if (cnt == 4)return true;
            return false;
        };
        vector dx = {1, -1, 0, 0};
        vector dy = {0, 0, 1, -1};
        vector block(n, vector(2, vector<int>(4)));
        for (int x = 0; x < n; ++x) {
            for (int k = 0; k < 2; ++k) {
                for (int i = 0; i < 2; ++i) {
                    string s;
                    cin >> s;
                    for (int j = 0; j < 2; ++j) {
                        if (s[j] == '#')block[x][k][2 * i + j] = 1;
                    }
                }
            }
        }
        auto drop_h = [&](int pos, vector<int> bl_st) {
            int H = -1;
            if(*std::max_element(bl_st.begin(), bl_st.end())==0)return H;
            int sz=st[0].size();
            for (int i = sz- 1; i >= 0; i--) {
                if (st[pos][i] == 1) {
                    H = i;
                    break;
                }
            }
            if (bl_st[0] == 0)return H;
            return H + 1;
        };
        auto is_ingrid=[&](int pos,int Dx,int Dy){
            int x=pos/2,y=pos%2;
            int nx=x+Dx,ny=y+Dy;
            if(nx<0 or nx>=2 or ny<0 or ny>=2)return false;
            return true;
        };
        auto drop_block = [&](int idx, int bit) -> int {
            int Dx = 0, Dy = 0;
            int ret = 0;
            for (int i = 0; i < 4; ++i) {
                if (bit >> i & 1) {
                    Dx += dx[i];
                    Dy += dy[i];
                }
            }
            int mx_h = -1;
            for (int pos = 0; pos < 4; ++pos) {
                auto pos2 = pos + Dx * 2 + Dy;
                vector<int> bl_st = {block[idx][0][pos], block[idx][1][pos]};
                for (int i = 0; i < 2; ++i) {
                    if (block[idx][i][pos]==1) {
                       if(!is_ingrid(pos,Dx,Dy))return -1LL;
                    }
                }
                if(pos2<0 or pos2>=4)continue;
                mx_h = max(mx_h, drop_h(pos2, bl_st));
            }
            for (int pos = 0; pos < 4; ++pos) {
                auto pos2 = pos + Dx * 2 + Dy;
                if(!is_ingrid(pos,Dx,Dy))continue;
                vector<int> bl_st = {block[idx][0][pos], block[idx][1][pos]};
                for (int i = 0; i < 2; ++i) {
                    if(mx_h+i>=0 and mx_h+i<st[0].size())st[pos2][mx_h + i] |= bl_st[i];
                }
            }
            int sz=st[0].size();
            for (int i = sz-1; i>=0;--i) {
                if(ch(i)){
                    for (int pos = 0; pos < 4; ++pos) {
                        st[pos].erase(st[pos].begin() + i);
                    }
                    ret++;
                }
            }
            return ret;
        };
        int N = n * 4;
        auto cop_st = st;
        ll ans = 0;
        for (int bit = 0; bit < (1 << N); ++bit) {
            st = cop_st;
            ll now = 0;
            for (int i = 0; i < n; ++i) {
                int s = 4 * i;
                int now_bit = 0;
                for (int j = 0; j < 4; ++j) {
                    if (bit >> (j + s)&1) {
                        now_bit |= (1 << j);
                    }
                }
                auto val = drop_block(i, now_bit);
                if (val == -1)now = -100;
                now += val;
            }
            ans = max(ans, now);
        }
        cout << ans << "\n";
    }
}
accuracy: 1
time_ms: 70
memory_kb: 3400
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;

auto move(vector<vector<vector<int>>> block, int dir) {
  int dy[] = {-1, -1, 0, 1, 1, 1, 0, -1};
  int dx[] = {0, 1, 1, 1, 0, -1, -1, -1};

  vector new_block(2, vector(2, vector(2, 0)));

  auto out_range = [&](int x) {
    return x < 0 || x >= 2;
  };

  for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        if (block[i][j][k] == 1 and (out_range(j + dy[dir]) or out_range(k + dx[dir]))) 
          return block;
        else if (!out_range(j + dy[dir]) && !out_range(k + dx[dir]))
          new_block[i][j + dy[dir]][k + dx[dir]] = block[i][j][k];
      }
    }
  }
  return new_block;
}

void fall(vector<vector<vector<int>>> &field, vector<vector<vector<int>>> block) {
  int i = 14;
  auto intersect = [&](int i) {
    if (i == 0) return true;
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        if ((field[i - 1][j][k] and block[0][j][k])
            or (field[i][j][k] and block[1][j][k])) 
          return true;
      }
    }
    return false;
  };

  while (!intersect(i)) i--;

  for (int j = 0; j < 2; j++) {
    for (int k = 0; k < 2; k++) {
      if (block[0][j][k]) field[i][j][k] = block[0][j][k];
      if (block[1][j][k]) field[i + 1][j][k] = block[1][j][k];
    }
  }
}

bool delete_4(vector<vector<vector<int>>> &field, int i) {
  auto full = [&]() {
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        if (!field[i][j][k]) return false;
      }
    }
    return true;
  };

  if (full()) {
    for (; i < 15; i++) {
      for (int j = 0; j < 2; j++) {
        for (int k = 0; k < 2; k++) {
          field[i][j][k] = field[i + 1][j][k];
        }
      }
    }
    for (int j = 0; j < 2; j++) {
      for (int k = 0; k < 2; k++) {
        field[15][j][k] = 0;
      }
    }
    return true;
  }
  else {
    return false;
  }
}

int main() {
  int h, n;
  while (cin >> h >> n, h > 0) {
    vector org_field(16, vector(2, vector(2, 0)));
    vector org_blocks(3, vector(2, vector(2, vector(2, 0))));

    for (int i = 0; i < h; i++) {
      for (int j = 0; j < 2; j++) {
        for (int k = 0; k < 2; k++) {
          char ch;
          cin >> ch;
          if (ch == '#')
            org_field[i][j][k] = 1;
        }
      }
    }

    for (int n_ = 0; n_ < n; n_++) {
      for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 2; j++) {
          for (int k = 0; k < 2; k++) {
            char ch;
            cin >> ch;
            if (ch == '#')
              org_blocks[n_][i][j][k] = 1;
          }
        }
      }
    }

    auto empty_first = [&](int n_) {
      for (int j = 0; j < 2; j++) {
        for (int k = 0; k < 2; k++) {
          if (org_blocks[n_][0][j][k] == 1) return false;
        }
      }
      return true;
    };
    for (int n_ = 0; n_ < n; n_++) {
      if (empty_first(n_)) {
        for (int j = 0; j < 2; j++) {
          for (int k = 0; k < 2; k++) {
            org_blocks[n_][0][j][k] = org_blocks[n_][1][j][k];
            org_blocks[n_][1][j][k] = 0;
          }
        }
      }
    }

    int ans = 0;
    for (int d1 = 0; d1 < 8; d1++) {
      for (int d2 = 0; d2 < 8; d2++) {
        for (int d3 = 0; d3 < 8; d3++) {
          auto field = org_field;
          auto blocks = org_blocks;
          blocks[0] = move(blocks[0], d1);
          blocks[1] = move(blocks[1], d2);
          blocks[2] = move(blocks[2], d3);

          auto print_field = [&]() {
            cout << "--field--" << endl;
            for (int i = 0; i < 16; i++) {
              for (int j = 0; j < 2; j++) {
                for (int k = 0; k < 2; k++) {
                  cout << field[i][j][k];
                }
                cout << endl;
              }
              cout << endl;
            }
            cout << "--field--" << endl;
          };

          auto print_blocks = [&]() {
            cout << "--blocks--" << endl;
            for (int n_ = 0; n_ < 3; n_++) {
              for (int i = 0; i < 2; i++) {
                for (int j = 0; j < 2; j++) {
                  for (int k = 0; k < 2; k++) {
                    cout << blocks[n_][i][j][k];
                  }
                  cout << endl;
                }
              }
              cout << endl;
            }
            cout << "--blocks--" << endl;
          };

          // print_blocks();

          int tmp = 0;
          for (int k = 0; k < 3; k++) {
            fall(field, blocks[k]);

            // print_field();
            for (int i = 0; i < 16; i++) {
              if (delete_4(field, i)) {
                tmp++;
                i--;
              }
            }
            // print_field();
          }

          ans = max(ans, tmp);
        }
      }
    }

    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 130
memory_kb: 3364
final_rank: 18

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <deque>
#include <queue>
#include <string>
#include <iomanip>
#include <set>
#include <unordered_set>
#include <map>
#include <unordered_map>
#include <utility>
#include <stack>
#include <random>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <assert.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
using namespace std;
using ll=long long;
#define read(x) cin>>(x);
#define readll(x) ll (x);cin>>(x);
#define readS(x) string (x);cin>>(x);
#define readvll(x,N) vector<ll> (x)((N));for(int i=0;i<(N);i++){cin>>(x)[i];}
#define rep(i,N) for(ll (i)=0;(i)<(N);(i)++)
#define rep2d(i,j,H,W) for(ll (i)=0;(i)<(H);(i)++)for(ll (j)=0;(j)<(W);j++)
#define yn {cout<<"Yes"<<endl;}else{cout<<"No"<<endl;}

#define is_in(x,y) (0<=(x) && (x)<2 && 0<=(y) && (y)<2)

long long powll(long long x,long long n){
  long long res=1;
  while(n>0){
    if(n&1){
      res*=x;
    }
    x*=x;
    n>>=1;
  }
  return res;
}

inline bool is_in3d(const vector<vector<vector<ll>>>& b,ll dx,ll dy){
  for(ll i=0;i<2;i++){
    for(ll x=0;x<2;x++){
      for(ll y=0;y<2;y++){
        if(b[i][x][y]==1 && !is_in(x+dx,y+dy)){
          return false;
        }
      }
    }
  }
  return true;
}

inline vector<vector<vector<ll>>> moved(const vector<vector<vector<ll>>>& b,ll dx,ll dy){
  vector<vector<vector<ll>>> res(2,vector<vector<ll>>(2,vector<ll>(2)));
  for(ll i=0;i<2;i++){
    for(ll x=0;x<2;x++){
      for(ll y=0;y<2;y++){
        if(b[i][x][y]==1){
          res[i][x+dx][y+dy]=1;
        }
      }
    }
  }
  return res;
}

void solve(ll H,ll N){
  //cerr<<H<<" "<<N<<endl;
  ll S=H+2*N+2;
  //cerr<<"S: "<<S<<endl;
  vector<vector<vector<ll>>> d(S,vector<vector<ll>>(2,vector<ll>(2)));
  for(ll x=0;x<2;x++){
    for(ll y=0;y<2;y++){
      d[0][x][y]=1;
    }
  }
  const vector<pair<ll,ll>> ar={{0,0},{0,1},{0,-1},{1,0},{-1,0},{1,1},{-1,1},{1,-1},{-1,-1}};
  for(ll i=1;i<H+1;i++){
    for(ll x=0;x<2;x++){
      string c;
      cin>>c;
      for(ll y=0;y<2;y++){
        if(c[y]=='#'){
          d[i][x][y]=1;
        }
      }
    }
  }
  // for(ll i=S-1;i>=0;i--){
  //   for(ll x=0;x<2;x++){
  //     for(ll y=0;y<2;y++){
  //       cerr<<d[i][x][y]<<" ";
  //     }
  //   }
  //   cerr<<endl;
  // }
  // cerr<<endl;
  //cerr<<"c input"<<endl;
  ll ans=0;
  vector<vector<vector<vector<ll>>>> inputs(N,vector<vector<vector<ll>>>(2,vector<vector<ll>>(2,vector<ll>(2))));
  for(ll i=0;i<N;i++){
    for(ll j=0;j<2;j++){
      for(ll x=0;x<2;x++){
        string b;
        cin>>b;
        for(ll y=0;y<2;y++){
          if(b[y]=='#'){
            inputs[i][j][x][y]=1;
          }
        }
      }
    }
  }
  ll u=ar.size();
  //cerr<<"input end"<<endl;
  ll M=powll(u,N);
  for(ll i=0;i<M;i++){
    ll cnt=0;
    ll direct=i;
    ll flag=1;
    vector<vector<vector<ll>>> D=d;
    for(ll j=0;j<N;j++){
      ll dx=ar[direct%u].first,dy=ar[direct%u].second;
      //cerr<<"j: "<<j<<" ,direct: "<<direct<<" ,dx: "<<dx<<" ,dy: "<<dy<<endl;
      if(!is_in3d(inputs[j],dx,dy)){
        flag=0;
        //cerr<<"break"<<endl;
        break;
      }
      vector<vector<vector<ll>>> changed=moved(inputs[j],dx,dy);
      // for(ll l=1;l>=0;l--){
      //   for(ll x=0;x<2;x++){
      //     for(ll y=0;y<2;y++){
      //       cerr<<changed[l][x][y]<<" ";
      //     }
      //   }
      //   cerr<<endl;
      // }
      ll index=0;
      for(ll k=S-2;k>=0;k--){
        ll f2=1;
        for(ll l=0;l<2;l++){
          for(ll x=0;x<2;x++){
            for(ll y=0;y<2;y++){
              if(D[k+l][x][y]==1 && changed[l][x][y]==1){
                f2=0;
                //cerr<<"goto!"<<endl;
                goto point1;
              }
            }
          }
        }
        point1:;
        if(f2==0){
          //cerr<<"break: k: "<<k<<endl;
          index=k+1;
          break;
        }
      }
      //cerr<<"j:"<<j<<" ,dx: "<<dx<<" ,dy:"<<dy<<endl;
      //cerr<<"index: "<<index<<endl;
      for(ll l=0;l<2;l++){
        for(ll x=0;x<2;x++){
          for(ll y=0;y<2;y++){
            D[index+l][x][y]+=changed[l][x][y];
            assert(D[index+l][x][y]<=1);
          }
        }
      }
      for(ll l=0;l<2;l++){
        for(ll k=1;k<S;k++){
          ll f3=1;
          for(ll x=0;x<2;x++){
            for(ll y=0;y<2;y++){
              if(D[k][x][y]==0){
                f3=0;
                goto point2;
              }
            }
          }
          point2:;
          if(f3==0){
            continue;
          }
          cnt++;
          for(ll m=k+1;m<S;m++){
            for(ll x=0;x<2;x++){
              for(ll y=0;y<2;y++){
                D[m-1][x][y]=D[m][x][y];
              }
            }
          }
          for(ll x=0;x<2;x++){
            for(ll y=0;y<2;y++){
              D[S-1][x][y]=0;
            }
          }
          break;
        }
      }
      direct/=u;
    }
    if(flag==1){
      //cerr<<"cnt: "<<cnt<<endl;
      ans=max(ans,cnt);
    }
  }
  cout<<ans<<endl;
  return;
}

int main(){
  ll H,N;
  while(1){
    cin>>H>>N;
    if(H==0){
      break;
    }
    solve(H,N);
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3376
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;
typedef long long int LL;
typedef long long int ll;
typedef pair<long long int, long long int> pii;
typedef pair<double, double> pdd;

#define SORT(c) sort((c).begin(),(c).end())
#define BACKSORT(c) sort((c).begin(),(c).end(),std::greater<LL>())
#define FOR(i,a,b) for(LL i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)
#define SP << " " <<

typedef vector<vector<vector<int>>> STG;

LL mod = 1000000007;

struct status{
  int stage_i;
  int num;
  int score;
};

void copy(STG& src, STG& dist){
  REP(i,2){
    REP(j,2){
      REP(k,20){
        dist[i][j][k] = src[i][j][k];
      }
    }
  }
}



int main()
{
  cin.tie(0);
  ios::sync_with_stdio(false);
  
  while(true){
    LL H, N;
    cin >> H >> N;
    
    if(H==0){
      break;
    }

    STG vec(2, vector<vector<int>>(2, vector<int>(20, 0)));
    
    REP(i,2){
      REP(j,2){
        vec[i][j][0] = 99;
      }
    }
    
    REP(i,H){
      REP(j,2){
        string s;
        cin>>s;
        REP(k,2){
          if(s[k]=='#'){
            vec[j][k][i + 1] = 1;
          }
        }
      }
    }

    //3個目が多い方が上
    vector<STG> blocks(N,STG(2, vector<vector<int>>(2, vector<int>(2, 0))));
    
    REP(kaisu,N){
      REP(i,2){
        REP(j,2){
          string s;
          cin>>s;
          REP(k,2){
            if(s[k]=='#'){
              blocks[kaisu][j][k][i] = 2;
            }
          }
        }
      }
      
      {
        bool flag = true;

        REP(i,2){
          REP(j,2){
            if(blocks[kaisu][0][i][j]==0){
            }else{
              flag = false;
            }
          }
        }
        
        if (flag) {
          REP(i, 2) {
            REP(j, 2) {
              blocks[kaisu][0][i][j] = blocks[kaisu][1][i][j];
              blocks[kaisu][1][i][j] = 0;
            }
          }
        }
      }
      
      {
        bool flag = true;

        REP(i,2){
          REP(j,2){
            if(blocks[kaisu][i][0][j]==0){
            }else{
              flag = false;
            }
          }
        }
        
        if (flag) {
          REP(i, 2)
          {
            REP(j, 2) {
              blocks[kaisu][i][0][j] = blocks[kaisu][i][1][j];
              blocks[kaisu][i][1][j] = 0;
            }
          }
        }
      }
    }

    queue<status> q;

    STG s(2, vector<vector<int>>(2, vector<int>(20, 0)));

    q.push({0, 0, 0});
    
    int maxscore = 0;

    vector<STG> stgs(10000,STG(2, vector<vector<int>>(2, vector<int>(20, 0))));
    copy(vec, stgs[0]);

    int cnt = 0;

    while(!q.empty()){
      status nowstatus = q.front();
      q.pop();

      // cout << nowstatus.num SP nowstatus.score << endl;

      if(nowstatus.num == N){
        maxscore = max(maxscore, nowstatus.score);
        continue;
      }

      bool xflag = true;

      REP(i,2){
        REP(j,2){
          if(blocks[nowstatus.num][1][i][j]==0){
            
          }else{
            xflag = false;
          }
        }
      }
      
      bool yflag = true;

      REP(i,2){
        REP(j,2){
          if(blocks[nowstatus.num][i][1][j]==0){
            
          }else{
            yflag = false;
          }
        }
      }

      LL xcnt = xflag ? 2 : 1;
      LL ycnt = yflag ? 2 : 1;

      // cout << "cnt" SP xcnt SP ycnt << endl;

      REP(x,xcnt){
        REP(y,ycnt){
          int scorex = nowstatus.score;
          cnt++;
          copy(stgs[nowstatus.stage_i],stgs[cnt]);
          
          REP(i,2-x){
            REP(j,2-y){
              REP(k,2){
                stgs[cnt][i + x][j + y][k + 18] = blocks[nowstatus.num][i][j][k];
              }
            }
          }


          //otosu
          while(true){
            bool flag = true;
            REP(i, 2)
            {
              REP(j,2){
                REP(k,19){
                  if(stgs[cnt][i][j][k]==1||stgs[cnt][i][j][k]==99){
                      // cout << i SP j SP k << endl;
                    if(stgs[cnt][i][j][k+1]==2){
                      flag = false;
                    }
                  }
                }
              }
            }
            if(!flag){
              break;
            }
            
            //otoseru
            REP(i, 2)
            {
              REP(j,2){
                REP(k,19){
                  if(stgs[cnt][i][j][k+1]==2){
                    if(stgs[cnt][i][j][k]==0){
                      // cout << i SP j SP k << endl;
                      stgs[cnt][i][j][k] = stgs[cnt][i][j][k + 1];
                      stgs[cnt][i][j][k + 1] = 0;
                    }
                  }
                }
              }
            }
          }

          // cout << "hoge" << endl;

          //naosu
          REP(k,20){
            REP(i,2){
              REP(j,2){
                if(stgs[cnt][i][j][k]==2){
                  stgs[cnt][i][j][k] = 1;
                }
              }
            }
          }
          
          //kesu
          for (int k = 19; k >= 0; --k){
            bool flag = true;
            REP(i,2){
              REP(j,2){
                if(stgs[cnt][i][j][k]==1){
                  
                }else{
                  flag = false;
                }
              }
            }
            if(!flag){
              continue;
            }
            
            //keseru
            scorex++;
            FOR(kk,k,19){
              REP(i,2){
                REP(j,2){
                  stgs[cnt][i][j][kk] = stgs[cnt][i][j][kk + 1];
                  stgs[cnt][i][j][kk + 1] = 0;
                }
              }
            }
            
            // k--;
          }

          // cout << nowstatus.stage_i SP cnt SP xcnt SP ycnt SP x SP y SP nowstatus.num + 1 SP nowstatus.score << endl;

          q.push({cnt, nowstatus.num + 1, scorex});
        }
      }
    }

    cout << maxscore << endl;
    }
}
accuracy: 1
time_ms: 360
memory_kb: 8724
final_rank: 19

code_snippet: #include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
//constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-9;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

int func(vector<vector<string>>s, vector<vector<vector<string>>>v, int x, int y) {
	int ret = 0;
	vector<int>dx(N);
	vector<int>dy(N);
	for (int i = 0; i < N; i++) {
		dx[i] = x % 3 - 1;
		dy[i] = y % 3 - 1;
		x /= 3, y /= 3;
		for (int z = 0; z < 2; z++) {
			for (int h = 0; h < 2; h++) {
				for (int w = 0; w < 2; w++) {
					if (v[i][z][h][w] == '#') {
						if (dx[i] + w < 0)return 0;
						if (dx[i] + w >= 2)return 0;
						if (dy[i] + h < 0)return 0;
						if (dy[i] + h >= 2)return 0;
					}
				}
			}
		}
		vector<vector<string>>nx(2, vector<string>(2, string(2,',')));
		for (int z = 0; z < 2; z++) {
			for (int h = 0; h < 2; h++) {
				for (int w = 0; w < 2; w++) {
					if (h + dy[i] < 0)continue;
					if (h + dy[i] >= 2)continue;
					if (w + dx[i] < 0)continue;
					if (w + dx[i] >= 2)continue;
					nx[z][h + dy[i]][w + dx[i]] = v[i][z][h][w];
				}
			}
		}
		vector<vector<int>>height(2, vector<int>(2,-1));
		for (int i = 0; i < s.size(); i++) {
			for (int j = 0; j < 2; j++) {
				for (int k = 0; k < 2; k++) {
					if (s[i][j][k] == '#') {
						height[j][k] = i;
					}
				}
			}
		}
		int add = -1;
		for (int z = 0; z < 2; z++) {
			for (int h = 0; h < 2; h++) {
				for (int w = 0; w < 2; w++) {
					if (nx[z][h][w] == '#') {
						add = max(add, height[h][w] + 1 - z);
					}
				}
			}
		}
		for (int z = 0; z < 2; z++) {
			for (int h = 0; h < 2; h++) {
				for (int w = 0; w < 2; w++) {
					if (nx[z][h][w] == '#') {
						s[z + add][h][w] = '#';
					}
				}
			}
		}
	//	cout << dy[i] << " " << dx[i] << endl;
	//	for (auto j : s)for(auto k:j)cout << k << endl;
	//	cout << endl;
		for (int j = s.size() - 2; j >= 0; j--) {
			if (s[j][0] == "##"&&s[j][1] == "##") {
				ret++;
				for (int k = j; k < s.size() - 1; k++) {
					s[k] = s[k + 1];
				}
			}
		}
	}
	return ret;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	while (cin >> H >> N, H) {
		vector<vector<string>>s(H, vector<string>(2));
		for (auto &i : s) {
			for (auto &j : i)cin >> j;
		}
		for (int i = 0; i < 7; i++) {
			s.push_back(vector<string>(2, ".."));
		}
		vector<vector<vector<string>>>v(N, vector<vector<string>>(2, vector<string>(2)));
		for (auto &i : v)for (auto &j : i)for (auto &k : j)cin >> k;
		int ans = 0;
		for (int i = 0; i < pow(3, N); i++) {
			for (int j = 0; j < pow(3, N); j++) {
				ans = max(ans, func(s, v, i, j));
			}
		}
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 50
memory_kb: 3396
final_rank: 14

code_snippet: #include <bits/stdc++.h>
using namespace std;

template<class T>
bool chmax(T& a, const T& b) {
    if (a < b) { a = b; return true; }
    return false;
}
template<class T>
bool chmin(T& a, const T& b) {
    if (b < a) { a = b; return true; }
    return false;
}

// std::vector Declaration
template<typename T>
vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T, typename... Ts>
auto make_v(size_t a, Ts... ts) {
    return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}

// std::vector Declaration and Initialization
template<typename T>
vector<T> make_vector(size_t a, T x) { return vector<T>(a, x); }
template<typename T, typename U, typename... Ts>
auto make_vector(size_t a, U b, Ts... ts) {
    return vector<decltype(make_vector<T>(b,ts...))>(a, make_vector<T>(b, ts...));
}

// std::vector Input
template<typename T>
istream& operator>>(istream& is, vector<T>& v) {
    for (auto &e : v) is >> e;
    return is;
}

// std::vector Debug
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
    os << "[";
    bool a = 1;
    for (auto e : v) {
        os << (a ? "" : " ");
        os << e;
        a = 0;
    }
    os << "]";
    return os;
}

// std::array Debug
template<typename T, size_t n>
ostream& operator<<(ostream& os, const array<T, n>& v) {
    os << "[";
    bool a = 1;
    for (auto e : v) {
        os << (a ? "" : " ");
        os << e;
        a = 0;
    }
    os << "]";
    return os;
}

// std::deque Debug
template<typename T>
ostream& operator<<(ostream& os, const deque<T>& d) {
    os << "[";
    bool a = 1;
    for (auto e : d) {
        os << (a ? "" : " ");
        os << e;
        a = 0;
    }
    os << "]";
    return os;
}

// std::pair Debug
template<typename T, typename U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
    os << "(" << p.first << " " << p.second << ")";
    return os;
}

// std::set Debug
template<typename T>
ostream& operator<<(ostream& os, const set<T>& st) {
    os << "{";
    bool a = 1;
    for (auto e : st) {
        os << (a ? "" : " ");
        os << e;
        a = 0;
    }
    os << "}";
    return os;
}

// std::multiset Debug
template<typename T>
ostream& operator<<(ostream& os, const multiset<T>& st) {
    os << "{";
    bool a = 1;
    for (auto e : st) {
        os << (a ? "" : " ");
        os << e;
        a = 0;
    }
    os << "}";
    return os;
}

// std::map Debug
template<typename T, typename U>
ostream& operator<<(ostream& os, const map<T, U>& mp) {
    os << "{";
    bool a = 1;
    for (auto e : mp) {
        os << (a ? "" : " ");
        os << e.first << ":" << e.second;
        a = 0;
    }
    os << "}";
    return os;
}

// std::tuple Debug
template<int N, class Tuple>
void out(ostream& os, const Tuple& t){}
template<int N, class Tuple, class H, class ...Ts>
void out(ostream& os, const Tuple& t) {
    if (N) os << " ";
    os << get<N>(t);
    out<N+1,Tuple,Ts...>(os, t);
}
template<class ...Ts>
ostream& operator<<(ostream& os, const tuple<Ts...>& t) {
    os << "(";
    out<0,tuple<Ts...>,Ts...>(os, t);
    os << ")";
    return os;
}

// Debug
#define DUMP(x) cerr<<#x<<" = "<<(x)<<endl

// Weighted edge
template<typename T>
struct edge {
    int src, to;
    T cost;

    edge() {}
    edge(int to, T cost) : src(-1), to(to), cost(cost) {}
    edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

    friend ostream& operator<<(ostream& os, const edge& e) {
        return os << "(" << e.src << "->" << e.to << ":" << e.cost << ")";
    }
};

using LL = int64_t;

#define fs first
#define sc second

const int64_t MOD = 1e9+7;
int dy[] = {0, 0, 1, 0,-1, 1, 1,-1,-1},
    dx[] = {0, 1, 0,-1, 0, 1,-1, 1,-1};

struct Block {
    vector<vector<vector<char>>> data;
    Block() : data(make_vector<char>(2,2,2,'.')) {}

    friend ostream& operator<<(ostream& os, const Block& b) {
        os << endl;
        for (int k = 0; k < 2; ++k) {
            for (int i = 0; i < 2; ++i) {
                for (int j = 0; j < 2; ++j) {
                    os << b.data[k][i][j];
                }
                os << endl;
            }
            os << endl;
        }
        return os;
    }

    pair<Block, bool> shift(int dir) const {
        bool valid = true;
        Block ret;
        for (int k = 0; k < 2; ++k) {
            for (int i = 0; i < 2; ++i) {
                for (int j = 0; j < 2; ++j) {
                    int y = i + dy[dir], x = j + dx[dir];
                    if (y < 0 or 2 <= y or x < 0 or 2 <= x) {
                        if (data[k][i][j] == '#') {
                            valid = false;
                        }
                    } else {
                        ret.data[k][y][x] = data[k][i][j];
                    }
                }
            }
        }
        return { ret, valid };
    }
};

struct Board {
    vector<vector<vector<char>>> data;
    Board() {}
    Board(int k) : data(k, make_vector<char>(2,2,'.')) {}

    friend ostream& operator<<(ostream& os, const Board& b) {
        os << endl;
        for (int k = 0; k < b.data.size(); ++k) {
            for (int i = 0; i < 2; ++i) {
                for (int j = 0; j < 2; ++j) {
                    os << b.data[k][i][j];
                }
                os << endl;
            }
            os << endl;
        }
        return os;
    }

    pair<Board,int> clear() const {
        Board ret = Board(data.size());
        int height = 0, count = 0;
        for (int k = 0; k < data.size(); ++k) {
            if (data[k][0][0] == '#' and data[k][0][1] == '#' and
                data[k][1][0] == '#' and data[k][1][1] == '#') {
                ++count;
                continue;
            }
            for (int i = 0; i < 2; ++i) {
                for (int j = 0; j < 2; ++j) {
                    ret.data[height][i][j] = data[k][i][j];
                }
            }
            ++height;
        }
        return { ret, count };
    }

    Board drop(const Block& block) const {
        Board ret = *this;
        auto height = make_v<int>(2, 2);
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < 2; ++j) {
                for (int k = 0; k < data.size(); ++k) {
                    if (data[k][i][j] == '#') {
                        chmax(height[i][j], k+1);
                    }
                }
            }
        }

        int floor = -1;
        for (int i = 0; i < 2; ++i) {
            for (int j = 0; j < 2; ++j) {
                if (block.data[0][i][j] == '#') {
                    chmax(floor, height[i][j]);
                } else if (block.data[1][i][j] == '#') {
                    chmax(floor, height[i][j] - 1);
                }
            }
        }

        for (int k = 0; k < 2; ++k) {
            for (int i = 0; i < 2; ++i) {
                for (int j = 0; j < 2; ++j) {
                    if (block.data[k][i][j] == '#') {
                        ret.data[k + floor][i][j] = '#';
                    }
                }
            }
        }

        return ret;
    }
};

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);

    while (true) {
        int H, N; cin >> H >> N;
        if (H == 0) break;
        Board board(H + 2*N);
        for (int k = 0; k < H; ++k) {
            for (int i = 0; i < 2; ++i) {
                string s; cin >> s;
                for (int j = 0; j < 2; ++j) {
                    board.data[k][i][j] = s[j];
                }
            }
        }

        vector<Block> blocks(N);
        for (int t = 0; t < N; ++t) {
            for (int k = 0; k < 2; ++k) {
                for (int i = 0; i < 2; ++i) {
                    string s; cin >> s;
                    for (int j = 0; j < 2; ++j) {
                        blocks[t].data[k][i][j] = s[j];
                    }
                }
            }
        }

        vector<int> a(N+1);
        int ans = 0;
        while (!a[N]) {
            Board tmp = board;
            bool valid = true;
            int count = 0;
            for (int t = 0; t < N; ++t) {
                bool ok; Block block;
                tie(block, ok) = blocks[t].shift(a[t]);
                if (!ok) {
                    valid = false;
                    break;
                }
                tmp = tmp.drop(block);
                int cnt;
                tie(tmp, cnt) = tmp.clear();
                count += cnt;
            }
            if (valid) chmax(ans, count);
            for (int i = 0; ++a[i] == 9; ++i) a[i] = 0;
        }
        cout << ans << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 3092
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

//INSERT ABOVE HERE
const int MAX = 101;
int C[2][2][MAX];
int B[2][2][2][3];

int D[2][2][MAX];
int E[2][2][MAX];
signed main(){
  int h,n;
  while(cin>>h>>n,h){
    memset(C,0,sizeof(C));
    for(int i=0;i<h;i++){
      string s[2];
      cin>>s[0]>>s[1];
      for(int j=0;j<2;j++)
        for(int k=0;k<2;k++)
          C[j][k][i]=s[j][k]=='#';
    }

    for(int t=0;t<n;t++){
      for(int i=0;i<2;i++){
        string s[2];
        cin>>s[0]>>s[1];
        for(int j=0;j<2;j++)
          for(int k=0;k<2;k++)
            B[j][k][i][t]=s[j][k]=='#';
      }
    }

    int ans=0;
    int sz=1;
    for(int i=0;i<n;i++) sz*=9;
    for(int bit=0;bit<sz;bit++){
      vector<int> dj(n),dk(n);
      int tmp=bit;
      // cout<<tmp<<endl;
      for(int t=0;t<n;t++){
        dj[t]=(tmp%3)-1;
        tmp/=3;
        dk[t]=(tmp%3)-1;
        tmp/=3;
      }
      auto in=[&](int j,int k){return 0<=j&&j<2&&0<=k&&k<2;};

      for(int i=0;i<MAX;i++)
        for(int j=0;j<2;j++)
          for(int k=0;k<2;k++)
            D[j][k][i]=C[j][k][i];

      int flg=0;
      int res=0;
      for(int t=0;t<n;t++){
        int nx[2][2][2]={};
        for(int i=0;i<2;i++)
          for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
              if(B[j][k][i][t]&&!in(j+dj[t],k+dk[t])) flg=1;

        //cout<<dj[0]<<" "<<dk[0]<<":"<<flg<<endl;
        if(flg) break;

        for(int i=0;i<2;i++)
          for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
              if(B[j][k][i][t])
                nx[j+dj[t]][k+dk[t]][i]=1;
        {
          int sm=0;
          for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
              sm+=nx[j][k][0];
          if(sm==0)
            for(int j=0;j<2;j++)
              for(int k=0;k<2;k++)
                swap(nx[j][k][0],nx[j][k][1]);
        }

        int y=MAX-10;
        for(;y>=0;y--){
          int mx=0;
          for(int i=0;i<2;i++){
            for(int j=0;j<2;j++){
              for(int k=0;k<2;k++){
                D[j][k][y+i]+=nx[j][k][i];
                chmax(mx,D[j][k][y+i]);
              }
            }
          }

          for(int i=0;i<2;i++)
            for(int j=0;j<2;j++)
              for(int k=0;k<2;k++)
                D[j][k][y+i]-=nx[j][k][i];

          if(mx==2){
            y++;
            break;
          }
          if(y==0) break;
        }
        // cout<<t<<":"<<dj[t]<<" "<<dk[t]<<":"<<y<<endl;

        for(int i=0;i<2;i++)
          for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
              D[j][k][y+i]+=nx[j][k][i];

        for(int i=0;i<MAX;i++)
          for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
              E[j][k][i]=0;

        for(int i=0,p=0;i<MAX;i++){
          int sum=0;
          for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
              sum+=D[j][k][i];
          if(sum==4){
            res++;
            continue;
          }
          for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
              E[j][k][p]=D[j][k][i];
          p++;
        }

        for(int i=0;i<MAX;i++)
          for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
              D[j][k][i]=E[j][k][i];
      }
      if(flg) continue;
      chmax(ans,res);
    }
    cout<<ans<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3140
final_rank: 3

code_snippet: #include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <climits>
#include <cstring>

#define rep(i, m, n) for(int i=int(m);i<int(n);i++)
#define all(c) begin(c),end(c)

template<typename T1, typename T2>
inline void chmin(T1 &a, T2 b) { if (a > b) a = b; }

template<typename T1, typename T2>
inline void chmax(T1 &a, T2 b) { if (a < b) a = b; }

//改造
typedef long long int ll;
using namespace std;
#define INF (1 << 30) - 1
#define INFl (ll)5e15
#define DEBUG 0 //デバッグする時1にしてね
#define dump(x)  cerr << #x << " = " << (x) << endl
#define MOD 1000000007


//ここから編集する
class Solve {
public:
    int H, N;
    vector<vector<vector<char>>> init;

//    vector<vector<int>> drop;
    vector<vector<vector<vector<char>>>> drop;

    int run(vector<vector<vector<vector<char>>>> &block) {
        auto state = init;
        int ret = 0;

        for (int i = 0; i < block.size(); ++i) {
            {
                bool flag = true;
                for (int l = 0; l < 2; ++l) {
                    for (int c = 0; c < 2; ++c) {
                        if (block[i][0][l][c] == '#') flag = false;
                    }
                }
                if (flag) {
                    for (int l = 0; l < 2; ++l) {
                        for (int c = 0; c < 2; ++c) {
                            if (block[i][1][l][c] == '#') {
                                block[i][0][l][c] = '#';
                                block[i][1][l][c] = '.';
                            }
                        }
                    }
                }
            }

            //設置
            int sh = H + 2 * i;
            for (int dh = 0; dh < 2; ++dh) {
                for (int x = 0; x < 2; ++x) {
                    for (int y = 0; y < 2; ++y) {
                        state[sh + dh][x][y] = block[i][dh][x][y];
                    }
                }
            }

            //落とす
            int h = sh;
            // state[h]が空ならhを+1する しません

            auto down = [&]() {
                for (int l = 0; l < 2; ++l) {
                    for (int c = 0; c < 2; ++c) {
                        if (block[i][0][l][c] == '#') {
                            state[h - 1][l][c] = state[h][l][c];
                            state[h][l][c] = '.';
                        }
                    }
                }
                for (int l = 0; l < 2; ++l) {
                    for (int c = 0; c < 2; ++c) {
                        if (block[i][1][l][c] == '#') {
                            state[h][l][c] = state[h + 1][l][c];
                            state[h + 1][l][c] = '.';
                        }
                    }
                }
                h--;
            };
            while (true) {
                if (h == 0) break;
                //hのしたにブロックがあるなら終了
                bool blockflag = false;
//                for (int l = 0; l < 2; ++l) {
//                    for (int c = 0; c < 2; ++c) {
//                        if (state[h][l][c] == '#' && state[h - 1][l][c] == '#') blockflag = true;
//                    }
//                }
                for (int dh = 0; dh < 2; ++dh) {
                    for (int l = 0; l < 2; ++l) {
                        for (int c = 0; c < 2; ++c) {
                            if (dh == 0) {
                                if (block[i][dh][l][c] == '#' && state[h + dh - 1][l][c] == '#') {
                                    blockflag = true;
                                }
                            } else {
                                if (block[i][dh][l][c] == '#' &&
                                    block[i][dh - 1][l][c] != '#' &&
                                    state[h + dh - 1][l][c] == '#') {
                                    blockflag = true;
                                }
                            }
                        }
                    }
                }


                if (blockflag) break;
                down();
            }

            //消せるやつがあるなら消す

            auto deletable = [&]() {
                for (int hh = 0; hh < state.size(); ++hh) {
                    bool flag = true;
                    for (int l = 0; l < 2; ++l) {
                        for (int c = 0; c < 2; ++c) {
                            if (state[hh][l][c] == '.') flag = false;
                        }
                    }
                    if (flag) return hh;
                }
                return -1;
            };

            while (true) {
                int hh = deletable();
                if (hh == -1) break;
                ret++;
                for (int l = 0; l < 2; ++l) {
                    for (int c = 0; c < 2; ++c) {
                        state[hh][l][c] = '.';
                    }
                }

                for (; hh + 1 < state.size(); ++hh) {
                    for (int l = 0; l < 2; ++l) {
                        for (int c = 0; c < 2; ++c) {
                            state[hh][l][c] = state[hh + 1][l][c];
                            state[hh + 1][l][c] = '.';
                        }
                    }
                }
            }
        }
        return ret;
    }

    int getketa(int val, int p, int d = 3) {
        val /= (int) round(pow(d, p));
        return val % d;
    }

    bool solve() {
        cin >> H >> N;
        if (H == 0) return false;
        init.resize(H + 6, vector<vector<char>>(2, vector<char>(2, '.')));
//        drop.resize(N, vector<int>(2, 0));
        drop.resize(N, vector<vector<vector<char>>>(2, vector<vector<char>>(2, vector<char>(2, '.'))));

        for (int i = 0; i < H; ++i) {
            for (int j = 0; j < 2; ++j) {
                for (int k = 0; k < 2; ++k) {
                    cin >> init[i][j][k];
                }
            }
        }

        for (int i = 0; i < N; ++i) {
            for (int k = 0; k < 2; ++k) {
                for (int l = 0; l < 2; ++l) {
                    for (int c = 0; c < 2; ++c) {
                        cin >> drop[i][k][l][c];
                    }
                }
            }
        }

        int ans = 0;
        vector<vector<vector<vector<char>>>>
                block(N, vector<vector<vector<char>>>(2, vector<vector<char>>(2, vector<char>(2, '.'))));


//        for (int dl = -1; dl <= 1; ++dl) {
//            for (int dc = -1; dc <= 1; ++dc) {
//
//            }
//        }
        for (int bit = 0; bit < (int) round(pow(3, 2 * N)); ++bit) {
//            vector<vector<vector<int>>> dlc(N, vector<vector<int>>(2, vector<int>(2, 0)));
//            vector<vector<int>> dl(N, vector<int>(2, 0));
//            vector<vector<int>> dc(N, vector<int>(2, 0));
            vector<int> dl(N);
            vector<int> dc(N);

            for (int i = 0; i < N; ++i) {
//                for (int l = 0; l < 2; ++l) {
////                    for (int c = 0; c < 2; ++c) {
////                        dlc[i][l][c] = getketa(bit, 4 * i + 2 * h + lc) - 1;
////                    }
//                    int keta = 4 * i + l;
//                    dl[i][l] = getketa(bit, keta);
//                }
//                for (int c = 0; c < 2; ++c) {
//                    int keta = 4 * i + c + 2;
//                    dc[i][c] = getketa(bit, keta);
//                }
                dl[i] = getketa(bit, 2 * i) - 1;
                dc[i] = getketa(bit, 2 * i + 1) - 1;
            }

            //ずらす
            if (dl[0] == 0 && dl[1] == 1 && dc[0] == 0 && dc[1] == 1) {
                int tapi = 79;
            }
            bool flag = true;
            block.assign(N, vector<vector<vector<char>>>(2, vector<vector<char>>(2, vector<char>(2, '.'))));

            for (int i = 0; i < N; ++i) {
                for (int h = 0; h < 2; ++h) {
                    for (int l = 0; l < 2; ++l) {
                        for (int c = 0; c < 2; ++c) {
                            int nl = l + dl[i];
                            int nc = c + dc[i];
                            if ((nl < 0 || nl >= 2) && drop[i][h][l][c] == '#') {
                                flag = false;
                                continue;
                            }
                            if ((nc < 0 || nc >= 2) && drop[i][h][l][c] == '#') {
                                flag = false;
                                continue;
                            }
                            if (drop[i][h][l][c] == '#')
                                block[i][h][nl][nc] = drop[i][h][l][c];
                        }
                    }
                }
            }


//            for (int i = 0; i < N; ++i) {
//                for (int j = 0; j < 2; ++j) {
//                    for (int h = 0; h < 2; ++h) {
//                        for (int w = 0; w < 2; ++w) {
//                            int pt = i * 8 + j * 4 + h * 2 + w;
//                            if (bit >> pt & 1) {
//                                block[i][j][h][w] = '#';
//                            } else {
//                                block[i][j][h][w] = '.';
//                            }
//                        }
//                    }
//                }
//            }

//            bool check = true;
//            for (int i = 0; i < N; ++i) {
//                for (int j = 0; j < 2; ++j) {
//                    int cnt = 0;
//                    for (int h = 0; h < 2; ++h) {
//                        for (int w = 0; w < 2; ++w) {
//                            if (block[i][j][h][w] == '#') cnt++;
//                        }
//                    }
//                    if (drop[i][j] != cnt) check = false;
//                }
//            }


            if (flag) {
                int tmp = run(block);
                chmax(ans, tmp);
            }
        }

        cout << ans << endl;
        return true;

    }
};


int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);

    while (Solve().solve());

    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3344
final_rank: 9

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define INF 1001000100010001000
#define MOD 1000000007
#define EPS 1e-10
#define int long long
#define rep(i, N) for (int i = 0; i < N; i++)
#define Rep(i, N) for (int i = 1; i < N; i++)
#define For(i, a, b) for (int i = (a); i < (b); i++)
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define pii pair<int, int>
#define vi vector<int>
#define vvi vector<vi >
#define vb vector<bool>
#define vvb vector<vb >
#define vp vector< pii >
#define all(a) (a).begin(), (a).end()
#define Int(x) int x; cin >> x;
#define int2(x, y) Int(x); Int(y);
#define int3(x, y, z) Int(x); int2(y, z);
#define in(x, a, b) ((a) <= (x) && (x) < (b))
#define fir first
#define sec second
#define ffir first.first
#define fsec first.second
#define sfir second.first
#define ssec second.second
#define Decimal fixed << setprecision(10)

//int dxy[5] = {0, 1, 0, -1, 0};
// cmd

int H = 2, W = 2;

int dx[9] = {-1, -1, -1, 0, 0, 0, 1, 1, 1};
int dy[9] = {-1, 0, 1, -1, 0, 1, -1, 0, 1};

bool _moveable(int x, int y, int dir)
{
    //cout << "call _move : " << x << " " << y << " " << dir;
    int nx = x + dx[dir], ny = y + dy[dir];
    //cout << " -> (" << nx << ", " << ny << ")";
    //cout << " : " << (in(nx, 0, H) && in(ny, 0, W)) << endl;
    return (in(nx, 0, H) && in(ny, 0, W));
}

bool movable(vector<vvi> &block, int dir)
{
    bool state = true;
    rep(i, block.size()) rep(j, block[i].size()) rep(k, block[i][j].size()) {
        if (block[i][j][k]) state &= _moveable(j, k, dir);
    }
    return state;
}

vector<vvi> put(vector<vvi> table, const vector<vvi> &cube, int dir)
{
    auto ret = table;
    rep(i, cube.size()) rep(j, cube[i].size()) rep(k, cube[i][j].size()) {
        if (cube[i][j][k]) {
            ret[i][j+dx[dir]][k+dy[dir]] = 1;
        }
    }
    return ret;
}

vector<vvi> drop(vector<vvi> &table, vector<vvi> &cube, int dir)
{
    vector<vvi> nc(cube.size(), vvi(cube[0].size(), vi(cube[0][0].size(), 0)));
    rep(i, cube.size()) rep(j, cube[i].size()) rep(k, cube[i][j].size()) {
        if (cube[i][j][k]) {
            nc[i][j+dx[dir]][k+dy[dir]] = 1;
        }
    }
    {
        bool fl = true;
        rep(j, nc[1].size()) rep(k, nc[1][j].size()) {
            fl &= !nc[1][j][k];
        }
        if (fl) {
            rep(j, nc[0].size()) rep(k, nc[0][j].size()) {
                nc[1][j][k] = nc[0][j][k];
                nc[0][j][k] = 0;
            }
        }
    }

    auto ret = table;
    int droph = 1;
    Rep(hi, table.size()-2) {
        bool fl = true;
        rep(i, nc.size()) rep(j, nc[i].size()) rep(k, nc[i][j].size()) {
            fl &= (!table[i+hi+1][j][k] || !nc[i][j][k]);
        }
        if (fl) {
            droph = hi;
        } else {
            break;
        }
    }

    rep(i, nc.size()) rep(j, nc[i].size()) rep(k, nc[i][j].size()) {
        ret[i+droph+1][j][k] += nc[i][j][k];
    }
    return ret;
}

void slide(vector<vvi> &table)
{
    for (int i = table.size()-2; i >= 0; i--) {
        bool can = true, ari = false;
        rep(j, table[i].size()) rep(k, table[i][j].size()) {
            can &= !(table[i+1][j][k]);
            ari |= table[i][j][k];
        }
        if (can && ari) {
            for (; i >= 0; i--) {
                rep(j, table[i].size()) rep(k, table[i][j].size()) {
                    table[i+1][j][k] = table[i][j][k];
                    table[i][j][k] = 0;
                }
            }
            i = table.size()-1;
        }
    }
}

int clear(vector<vvi> &table)
{
    int ret = 0;
    rep(i, table.size()) {
        int fl = true;
        rep(j, table[i].size()) rep(k, table[i][j].size()) {
            fl &= table[i][j][k];
        }
        if (fl) {
            rep(j, table[i].size()) rep(k, table[i][j].size()) {
                table[i][j][k] = 0;
            }
            slide(table);
            ret += 4;
            i--;
        }
    }
    return ret;
}

void print(vector<vvi> &table)
{
    rep(i, table.size()) {
        cout << "====== " << i << " ======" << endl;
        rep(j, table[i].size()) {
            rep(k, table[i][j].size()) {
                cout << table[i][j][k];
            }
            cout << endl;
        }
    }
}


int solve(vector<vector<vvi>> &cube, vector<vvi> &table, int cnum)
{
    auto edit = table;
    //cout << "call solve : " << cnum << endl;
    if (cnum == cube.size()) {
        return 0;
    }
    int ret = 0;
    for (int i = 0; i < 9; i++) {
        //cout << "move : " << i << " " << movable(cube[cnum], i) << endl;
        if (movable(cube[cnum], i)) {
            //edit = put(table, cube[cnum], i);
            edit = drop(table, cube[cnum], i);
            int tmp = clear(edit);
            //print(edit);
            ret = max(ret, tmp + solve(cube, edit, cnum+1));
        }
    }
    return ret;
}
signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    int h, n;
    while (cin >> h >> n, n) {
        vector<vvi> table(50, vvi(2, vi(2, 0)));
        vector<vector<vvi>> cube(n, vector<vvi>(2, vvi(2, vi(2, 0))));
        rep(i, h) {
            rep(j, 2) {
                string tmp;
                cin >> tmp;
                rep(k, 2) {
                    table[table.size()-1-i][j][k] = (tmp[k] == '#');
                }
            }
        }

        rep(cnum, n) {
            for (int i = 1; i >= 0; i--) rep(j, 2) {
                string tmp;
                cin >> tmp;
                rep(k, 2) {
                    cube[cnum][i][j][k] = (tmp[k] == '#');
                }
            }
        }

        /*
        rep(cnum, n) {
            cout << "====== " << cnum << " ======" << endl;
            rep(i, cube[cnum].size()) {
                rep(j, cube[cnum][i].size()) {
                    rep(k, cube[cnum][i][j].size()) {
                        cout << cube[cnum][i][j][k];
                    }
                    cout << endl;
                }
            }
        }
        */

        cout << solve(cube, table, 0) / 4 << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3168
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;

int ans=0;
int n;
int blk[3][2][2][2];
int cnt=0;


int check(vector<vector<vector<int>>> s,int b,int h,int x,int y){
    if(h<=-1){
        return 0;
    }
    bool f=true;
    for(int i=0;i<2;i++){
        for(int j=0;j<2;j++){
            for(int k=0;k<2;k++) {
                if (s[h + i][y + j][x + k]==1 && blk[b][i][j][k]==1){
                    f=false;
                }
            }
        }
    }
    if(f){
        return check(s,b,h-1,x,y);
    }
    else return h+1;
}

vector<vector<vector<int>>> delblk(vector<vector<vector<int>>> t){
    for(int i=1;i<t.size();i++){
        bool f=true;
        for(int j=0;j<t[i].size();j++){
            for(int k=0;k<t[i][j].size();k++){
                if(t[i][j][k]!=1)f=false;
            }
        }
        if(f){
            cnt++;
            for(int j=i;j<15;j++){
                for(int k=1;k<3;k++){
                    for(int l=1;l<3;l++){
                        t[j][k][l]=t[j+1][k][l];
                    }
                }
            }
            i--;
        }
    }
    return t;
}

void dfs(int b,vector<vector<vector<int>>> s,int ma){
    if(b>=n){
        ans=max(ans,ma);
        return ;
    }
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            vector<vector<vector<int>>> t(s);
            int dpth=check(s,b,15,j,i);
            if(dpth==16)continue;
            //cout << b << " " <<  i << " " << j  << " " << dpth << endl;
            for(int k=0;k<2;k++) {
                for (int l = 0; l < 2; l++) {
                    for (int m = 0; m < 2; m++) {
                        if (blk[b][k][l][m] == 1) {
                            t[dpth + k][i + l][j + m] = 1;
                        }
                    }
                }
            }
            cnt=0;
            t=delblk(t);
            dfs(b+1,t,ma+cnt);
            // if(b==0){
            //     for(int i=3;i>=0;i--){
            //         for(int j=3;j>=0;j--){
            //             for(int k=0;k<4;k++){
            //                 cout << t[i][j][k] << " ";
            //             }cout << endl;
            //         }cout << endl;
            //     }
            // }
        }
    }
    
}

int main(){
    while(1){
        int h;
        cin >> h >> n;
        if(n==0)break;
        vector<vector<vector<int>>> s(17,vector<vector<int>>(4,vector<int>(4,0)));
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                s[0][i][j]=1;
            }
        }
        ans=0;
        for(int i=1;i<=h;i++){
            string tt;
            cin >> tt;
            for(int j=0;j<2;j++){
                if(tt[j]=='#'){
                    s[i][1][j+1]=1;
                }
            }
            cin >> tt;
            for(int j=0;j<2;j++){
                if(tt[j]=='#'){
                    s[i][2][j+1]=1;
                }
            }
        }
        for(int i=1;i<=16;i++){
            for(int j=0;j<4;j++){
                if(j==0||j==3){
                    for(int k=0;k<4;k++){
                        s[i][j][k]=1;       
                    }
                }else{
                    s[i][j][0]=1;
                    s[i][j][3]=1;
                }
            }
        }
        for(int i=0;i<n;i++){
            string tt[4];
            for(int j=0;j<4;j++){
                cin >> tt[j];
            }
            for(int j=0;j<4;j++){
                if(tt[j][0]=='#'){
                    blk[i][j/2][j%2][0]=1;
                }else{
                    blk[i][j/2][j%2][0]=0;
                }
            }
            for(int j=0;j<4;j++){
                if(tt[j][1]=='#'){
                    blk[i][j/2][j%2][1]=1;
                }else{
                    blk[i][j/2][j%2][1]=0;
                }
            }
        }
        // for(int i=0;i<10;i++){
        //     for(int j=0;j<4;j++){
        //         for(int k=0;k<4;k++){
        //             cout << s[i][j][k] << " ";
        //         }cout << endl;
        //     }cout << endl;
        // }
        // for(int i=1;i>=0;i--){
        //     for(int j=1;j>=0;j--){
        //         for(int k=0;k<2;k++){
        //             cout << blk[0][i][j][k] << " ";
        //         }cout << endl;
        //     }cout << endl;
        // }
        dfs(0,s,0);
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3252
final_rank: 8

code_snippet: #include <bits/stdc++.h>

using namespace std;
using ll = long long;
// #define int ll
using PII = pair<ll, ll>;

#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()

template<typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }
template<typename T> bool IN(T a, T b, T x) { return a<=x&&x<b; }
template<typename T> T ceil(T a, T b) { return a/b + !!(a%b); }

template<typename T> vector<T> make_v(size_t a) { return vector<T>(a); }
template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts) {
    return vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}
template<typename T,typename V> typename enable_if<is_class<T>::value==0>::type
fill_v(T &t, const V &v) { t=v; }
template<typename T,typename V> typename enable_if<is_class<T>::value!=0>::type
fill_v(T &t, const V &v ) { for(auto &e:t) fill_v(e,v); }

template<class S,class T>
ostream &operator <<(ostream& out,const pair<S,T>& a) {
    out<<'('<<a.first<<','<<a.second<<')'; return out;
}
template<class T>
ostream &operator <<(ostream& out,const vector<T>& a){
    out<<'[';
    for(const T &i: a) out<<i<<',';
    out<<']';
    return out;
}
template<class T>
ostream &operator <<(ostream& out, const set<T>& a) {
    out<<'{';
    for(const T &i: a) out<<i<<',';
    out<<'}';
    return out;
}
template<class T, class S>
ostream &operator <<(ostream& out, const map<T,S>& a) {
    out<<'{';
    for(auto &i: a) out<<i<<',';
    out<<'}';
    return out;
}

int dx[] = {0, 1, 0, -1}, dy[] = {1, 0, -1, 0}; // DRUL
const int INF = 1<<30;
const ll LLINF = 1LL<<60;
const ll MOD = 1000000007;

signed main(void)
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    ll test = 0;
    while(1) {
        ll h, n;
        cin >> h >> n;
        if(!h) break;
        vector<string> vv(h+2*n, string(4, '.'));
        REP(i, h) {
            string s, t;
            cin >> s >> t;
            vv[i] = s + t;
        }
        using P = pair<string, string>;
        vector<P> a(n);
        REP(i, n) {
            string s1, s2;
            cin >> s1 >> s2;
            a[i].second = s1 + s2;
            cin >> s1 >> s2;
            a[i].first = s1 + s2;
        }

        // cout << "init" << endl;
        // REP(i, h) cout << vv[i] << endl;
        // cout << endl;

        ll m = 1, ret = 0;
        REP(i, n) m *= 9;
        REP(mask, m) {
            // cout << "mask:" << mask << endl;
            vector<P> b(a);
            ll t = mask;
            bool muri = false;
            REP(i, n) {
                ll rot = t%9;
                t /= 9;

                if(rot == 0) {

                }
                // 右に寄せる
                else if(rot == 1) {
                    if(a[i].first[1]=='#'||a[i].first[3]=='#'||a[i].second[1]=='#'||a[i].second[3]=='#') muri = true;
                    b[i].first[0] = b[i].first[2] = b[i].second[0] = b[i].second[2] = '.';
                    b[i].first[1] = a[i].first[0];
                    b[i].first[3] = a[i].first[2];
                    b[i].second[1] = a[i].second[0];
                    b[i].second[3] = a[i].second[2];
                }
                // 左に寄せる
                else if(rot == 2) {
                    if(a[i].first[0]=='#'||a[i].first[2]=='#'||a[i].second[0]=='#'||a[i].second[2]=='#') muri = true;
                    b[i].first[1] = b[i].first[3] = b[i].second[1] = b[i].second[3] = '.';
                    b[i].first[0] = a[i].first[1];
                    b[i].first[2] = a[i].first[3];
                    b[i].second[0] = a[i].second[1];
                    b[i].second[2] = a[i].second[3];
                }
                // 上に寄せる
                else if(rot == 3) {
                    if(a[i].first[0]=='#'||a[i].first[1]=='#'||a[i].second[0]=='#'||a[i].second[1]=='#') muri = true;
                    b[i].first[2] = b[i].first[3] = b[i].second[2] = b[i].second[3] = '.';
                    b[i].first[0] = a[i].first[2];
                    b[i].first[1] = a[i].first[3];
                    b[i].second[0] = a[i].second[2];
                    b[i].second[1] = a[i].second[3];
                }
                // 下に寄せる
                else if(rot == 4) {
                    if(a[i].first[2]=='#'||a[i].first[3]=='#'||a[i].second[2]=='#'||a[i].second[3]=='#') muri = true;
                    b[i].first[1] = b[i].first[0] = b[i].second[1] = b[i].second[0] = '.';
                    b[i].first[2] = a[i].first[0];
                    b[i].first[3] = a[i].first[1];
                    b[i].second[2] = a[i].second[0];
                    b[i].second[3] = a[i].second[1];
                }
                // 左上に寄せる
                else if(rot == 5) {
                    if(a[i].first[1]=='#'||a[i].first[2]=='#'||a[i].first[0]=='#'||a[i].second[1]=='#'||a[i].second[2]=='#'||a[i].second[0]=='#') muri = true;
                    b[i].first[3] = b[i].second[3] = '.';
                    b[i].first[0] = a[i].first[3];
                    b[i].second[0] = a[i].second[3];
                }
                // 右上に寄せる
                else if(rot == 6) {
                    if(a[i].first[1]=='#'||a[i].first[0]=='#'||a[i].first[3]=='#'||a[i].second[1]=='#'||a[i].second[0]=='#'||a[i].second[3]=='#') muri = true;
                    b[i].first[2] = b[i].second[2] = '.';
                    b[i].first[1] = a[i].first[2];
                    b[i].second[1] = a[i].second[2];
                }
                // 左下に寄せる
                else if(rot == 7) {
                    if(a[i].first[0]=='#'||a[i].first[2]=='#'||a[i].first[3]=='#'||a[i].second[0]=='#'||a[i].second[2]=='#'||a[i].second[3]=='#') muri = true;
                    b[i].first[1] = b[i].second[1] = '.';
                    b[i].first[2] = a[i].first[1];
                    b[i].second[2] = a[i].second[1];
                }
                // 右下に寄せる
                else if(rot == 8) {
                    if(a[i].first[1]=='#'||a[i].first[2]=='#'||a[i].first[3]=='#'||a[i].second[1]=='#'||a[i].second[2]=='#'||a[i].second[3]=='#') muri = true;
                    b[i].first[0] = b[i].second[0] = '.';
                    b[i].first[3] = a[i].first[0];
                    b[i].second[3] = a[i].second[0];
                }
            }
            if(muri) continue;

            // REP(i, n) cout << b[i] << endl;

            ll cnt = 0;
            auto v(vv);
            REP(i, n) {
                bool flag1 = false, flag2 = false, stop = false;
                REP(j, 4) {
                    if(b[i].second[j]=='#') flag1 = true;
                    if(b[i].first[j]=='#') flag2 = false;
                }
                // 高さjにブロックの下の段が来るパターン
                for(ll j=h+2*n-1; j>=0; --j) {
                    if((j==0&&flag1) || (j&&v[j-1][0]=='#'&&v[j-1][0]==b[i].second[0]) || (j&&v[j-1][1]=='#'&&v[j-1][1]==b[i].second[1]) || (j&&v[j-1][2]=='#'&&v[j-1][2]==b[i].second[2]) || (j&&v[j-1][3]=='#'&&v[j-1][3]==b[i].second[3])) {
                        // cout << "hit second " << j << endl;
                        REP(k, 4) {
                            if(b[i].second[k]=='#') v[j][k] = '#';
                            if(b[i].first[k]=='#') v[j+1][k] = '#';
                        }
                        stop = true;
                        break;
                    }
                    if((v[j][0]=='#'&&v[j][0]==b[i].first[0]) || (v[j][1]=='#'&&v[j][1]==b[i].first[1]) || (v[j][2]=='#'&&v[j][2]==b[i].first[2]) || (v[j][3]=='#'&&v[j][3]==b[i].first[3])) {
                        // cout << "hit first " << j << endl;
                        REP(k, 4) {
                            if(b[i].second[k]=='#') v[j][k] = '#';
                            if(b[i].first[k]=='#') v[j+1][k] = '#';
                        }
                        stop = true;
                        break;
                    }
                }
                if(!stop) {
                    // cout << "hit first last " << endl;
                    REP(k, 4) {
                        if(b[i].first[k]=='#') v[0][k] = '#';
                    }
                }
                // REP(j, h+2*n) cout << "height=" << j << " " << v[j] << endl;
                // 消える段があったら消す
                REP(j, h+2*n) {
                    if(v[j][0]=='#'&&v[j][1]=='#'&&v[j][2]=='#'&&v[j][3]=='#') {
                        v[j][0] = v[j][1] = v[j][2] = v[j][3] = '.';
                        FOR(k, j, h+2*n-1) {
                            v[k][0] = v[k+1][0];
                            v[k][1] = v[k+1][1];
                            v[k][2] = v[k+1][2];
                            v[k][3] = v[k+1][3];
                        }
                        j--;
                        cnt++;
                    }
                }
            }
            chmax(ret, cnt);
        }

        cout << ret << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3240
final_rank: 6

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <cmath>
#include <set>
using namespace std;

constexpr int LIM = 32;

vector<vector<int>> box[LIM];


bool valid(vector<vector<int>> a0,vector<vector<int>> a1,vector<vector<int>> b0,vector<vector<int>> b1){
    for(int x=0;x<4;x++){
        for(int y=0;y<4;y++){
            if(a0[x][y] and b0[x][y]) return false;
        }
    }
    for(int x=0;x<4;x++){
        for(int y=0;y<4;y++){
            if(a1[x][y] and b1[x][y]) return false;
        }
    }
    return true;
}

void solve(int H,int N){
    for(int i=0;i<H;i++){
        string s[2]; cin >> s[0] >> s[1];
        for(int x=0;x<2;x++) for(int y=0;y<2;y++){
            if(s[x][y] == '#'){
                box[i][x+1][y+1] = 1;
            }
        }
    }

    int ans = 0;

    vector<vector<vector<vector<int>>>> boxes_t(N,vector<vector<vector<int>>>(4,vector<vector<int>>(4,vector<int>(4,0))));
    for(int i=0;i<N;i++){// i - th
        for(int j=0;j<2;j++){   // high
            string s[2]; cin >> s[0] >> s[1];
            //cerr << s[0] << " " << s[1] << endl;
            for(int x=0;x<2;x++){
                for(int y=0;y<2;y++){
                    if(s[x][y] == '#'){
                        //cerr << "NG " << i <<" " << j <<"  " << x << " " << y << endl;
                        boxes_t[i][j][x+1][y+1] = 1;
                    }
                }
            }
        }
    }

    for(int mask=0;mask<(1<<(4*N));mask++){
        //cerr << "mask " << mask << endl;
        int ans_cnt = 0;
        vector<vector<int>> tmp[LIM];
        for(int k=0;k<LIM;k++) tmp[k] = box[k];

        auto boxes = boxes_t;

        for(int idx=0;idx<N;idx++){
            int i = ((mask >> (idx*4)) % (1<<4)) / 4-1;
            int j = ((mask >> (idx*4)) % (1<<4)) % 4-1;
            if(i<-1 or i>1 or j<-1 or j>1) break;

            for(int h=0;h<2;h++){
                for(int x=0;x<4;x++){
                    for(int y=0;y<4;y++){
                        if(x+i>=0 and y+j>=0  and x+i<4 and y+j < 4) boxes[idx][h][x][y] = boxes_t[idx][h][x+i][y+j];
                        else  boxes[idx][h][x][y] = 0;
                    }
                }
            }

            //for(int x=0;x<4;x++){
            //    for(int y=0;y<4;y++){
            //        cerr << boxes[0][1][x][y];
            //    }
            //    cerr << endl;
            //}

            bool oktable = true;
            for(int h=0;h<2;h++){
                for(int x=0;x<4;x++){
                    for(int y=0;y<4;y++){
                        if((x == 0 or x == 3 or y == 0 or y == 3) and boxes[idx][h][x][y]){
                            oktable = false;
                            break;
                        }
                    }
                }
            }

            if(!oktable) break;
            // OK

            int okh;
            int limit = 0;
            int po = 0;
            for(int x=0;x<4;x++) for(int y=0;y<4;y++) if(boxes[idx][0][x][y]) po++;
            if(po == 0) limit = -1;
            ////cerr << "limit " << limit << endl;
            for(okh = LIM-2; okh>=0; okh--){
                if(!valid(tmp[okh],tmp[okh+1],boxes[idx][0],boxes[idx][1])){
                    break;
                }
            }
            okh++;

            //if (okh == 0) {
            //    cout << idx << " " << i << " " << j << endl;
            //}

            if(okh == 0 and limit == -1){
                bool ok = true;
                for(int x=0;x<4;x++){
                    for(int y=0;y<4;y++){
                        if(tmp[0][x][y] and boxes[idx][1][x][y]){
                            ok = false;
                            break;
                        }
                    }
                }
                if(ok){
                    okh = -1;
                }
            }

            for(int h=0;h<2;h++){
                for(int x=0;x<4;x++){
                    for(int y=0;y<4;y++){
                        if(okh+h>=0) tmp[okh+h][x][y] |= boxes[idx][h][x][y];
                    }
                }
            }

            set<int> del;
            for(int i=0;i<LIM;i++){
                int cnt = 0;
                for(int x=0;x<4;x++){
                    for(int y=0;y<4;y++){
                        if(tmp[i][x][y]){
                            cnt++;
                        }
                    }
                }
                if(cnt == 4){
                    del.insert(i);
                }
            }

            ans_cnt += del.size();

            if(del.size() == 1){
                int d = *del.begin();
                for(int i=0;i<LIM;i++){
                    if(i>=d){
                        if(i+1<LIM)tmp[i] = tmp[i+1];
                        else{
                            for(int x=0;x<4;x++) for(int y=0;y<4;y++) tmp[i][x][y]=0;
                        }
                    }
                }
            }else if(del.size() == 2){
                int d = *del.begin();
                for(int i=0;i<LIM;i++){
                    if(i>=d){
                        if(i+2<LIM) tmp[i] = tmp[i+2];
                        else{
                            for(int x=0;x<4;x++) for(int y=0;y<4;y++) tmp[i][x][y]=0;
                        }
                    }
                }
            }

                // for(int h=0;h<2;h++){
                //     for(int x=0;x<4;x++){
                //         for(int y=0;y<4;y++){
                //             cerr << tmp[h][x][y];
                //         }
                //         cerr << endl;
                //     }
                //     cerr << endl;
                // }

        }

        ans = max(ans,ans_cnt);
    }
    cout << ans << endl;
}


int main(){
    for(int i=0;i<LIM;i++){
        box[i] = vector<vector<int>>(4,vector<int>(4,0));
    }

    while(1){
        int h,n;
        cin >> h >> n;
        if(h == 0 and n == 0) break;
        for(int i=0;i<4;i++) for(int j=0;j<4;j++) for(int k=0;k<LIM;k++) box[k][i][j] = 0;
        solve(h,n);
    }
}
accuracy: 1
time_ms: 1420
memory_kb: 3260
final_rank: 20

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
#define REP(i, n) for(int (i)=0; (i)<(n); (i)++)
#define NIREP(i, n) for((i)=0; (i)<(n); (i)++) //non-initialized rep
const int limit = 20;
int dx[9] = {1, 1, 1, 0, 0, 0,-1,-1,-1};
int dy[9] = {1, 0,-1, 1, 0,-1, 1, 0,-1};
typedef vector<vector<bool> > vec2D;
vec2D defplane(2, vector<bool>(2, false));
bool canmove(int n, vec2D &a){
    REP(x,2) REP(y,2){
        int nx = x+dx[n];
        int ny = y+dy[n];
        if(a[x][y] && (nx<0 || 1<nx || ny<0 || 1<ny)){
            return false;
        }
    }
    return true;
}
bool canmove(int n, vector<vec2D> &a){
    REP(i, (int)a.size()){
        if(!canmove(n, a[i])) return false;
    }
    return true;
}
vector<vec2D> convert(int n, vector<vec2D> &a){
    vector<vec2D> ret(2, defplane);
    REP(x,2) REP(y,2) {
        int nx = x+dx[n];
        int ny = y+dy[n];
        if(0<=nx && nx<=1 && 0<=ny && ny<=1){
            REP(i,2) ret[i][nx][ny] = a[i][x][y];
        }
    }
    return ret;
}
bool isoverlap(vec2D &a, vec2D &b){
    REP(x,2) REP(y,2){
        if(a[x][y] && b[x][y]) return true;
    }
    return false;
}

int main(){
    while(1){
        int h,n;
        cin >> h >> n;
        if(h==0) break;
        
        vector<vec2D> c(limit, defplane);
        vector<vector<vec2D> > b(3, vector<vec2D>(2, defplane));
        REP(r,h) REP(i,2) REP(j,2){
            char in;
            cin >> in;
            if(in == '#') c[r][i][j] = true;
        }
        REP(k,n) REP(r,2) REP(i,2) REP(j,2){
            char in;
            cin >> in;
            if(in == '#') b[k][r][i][j] = true;
        }

        
        int ans = 0;
        int var[3];
        NIREP(var[0], 9) NIREP(var[1], 9) NIREP(var[2], 9){
            if(!canmove(var[0], b[0]) || !canmove(var[1], b[1]) || !canmove(var[2], b[2])){
                continue;
            }
            int count = 0;
            vector<vec2D> field = c;
            REP(i,3){
                //make block (moved)
                vector<vec2D> block = convert(var[i], b[i]);
                if(block[0] == defplane) swap(block[0], block[1]);
                //height of falling block
                int s=limit-2;
                while(s>0 && !isoverlap(block[0], field[s-1]) && !isoverlap(block[1], field[s])){
                    s--;
                }
                //put
                REP(r,2) REP(x,2) REP(y,2){
                    if(block[r][x][y]){
                        field[s+r][x][y] = true;
                    }
                }
                //delete and count
                for(int i=limit-1; i>=0; i--){
                    bool full = true;
                    REP(x,2) REP(y,2){
                        if(!field[i][x][y]) full = false;
                    }
                    if(full){
                        count++;
                        field.erase(field.begin()+i);
                        field.push_back(defplane);
                    }
                }
            }
            ans = max(ans, count);
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3104
final_rank: 2

code_snippet: #include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <utility>
#include <algorithm>
#include <tuple>
using namespace std;
using Board = vector< vector< vector<int> > >;

int H, N;

int dx[] = {0, 1, -1, 0, 1, -1, 0, 1, -1};
int dy[] = {0, 0, 0, 1, 1, 1, -1, -1, -1};

// 全て埋まっている: 1, なにも埋まっていない: 2, それ以外: 0
int comp(Board board, int z) {
    bool complete = true, none = true;
    for(int x=0; x<2; x++) {
        for(int y=0; y<2; y++) {
            if(board[z][x][y] == 1) {
                none = false;
            }
            else {
                complete = false;
            }
        }
    }
    if(complete) return 1;
    if(none) return 2;
    return 0;
}

void boardfall(Board &board) {
    for(int z = 20; z > 0; z--) {
        int top = z - 1;
        if(comp(board, top) == 2) {
            swap(board[z], board[top]);
        }
    }
}

void print_board(Board board) {
    for(int z=0; z<20; z++) {
        if(comp(board, z) == 2) continue;
        printf("board (z = %d):\n", z);
        for(auto x : board[z][0]) cout << x;
        cout << endl;
        for(auto x : board[z][1]) cout << x;
        cout << endl << endl;
    }
}

pair<Board, int> modify_board(Board board, Board block) {
    int z;
    // block の下の段に何もなければ swap
    if(comp(block, 0) == 2) swap(block[0], block[1]);

    for(z = 20; z > 0; z--) {
        // block の底面が z に位置する
        // 下に行けるかどうかのチェック
        int top = z - 1;
        bool ok = true;
        for(int dz=0; dz<2; dz++) {
            for(int x=0; x<2; x++) {
                for(int y=0; y<2; y++) {
                    if(board[top+dz][x][y] && block[dz][x][y]) ok = false;
                }
            }
        }

        if(!ok) break;
    }

    // printf("! z = %d\n", z);

    for(int dz=0; dz<2; dz++) {
        for(int x=0; x<2; x++) {
            for(int y=0; y<2; y++) {
                board[z+dz][x][y] |= block[dz][x][y];
            }
        }
    }

    int get_combo = 0;
    for(int z=0; z<20; z++) {
        // 全て埋まっている
        if(comp(board, z) == 1) {
            for(int x=0; x<2; x++) {
                for(int y=0; y<2; y++) {
                    board[z][x][y] = 0;
                }
            }
            get_combo++;
        }
    }

    boardfall(board);
    return make_pair(board, get_combo);
}

int dfs(const Board board, const vector<Board> &blocks, int idx=0, int combo=0) {
    // printf("step: %d\n", idx+1);
    // print_board(board);

    if(idx == N) return combo;
    int ret = 0;

    // ブロックの水平移動
    for(int k=0; k<9; k++) {
        bool ok = true;
        Board block = blocks[idx];
        Board n_block = Board(2, vector< vector<int> >(2, vector<int>(2)));
        for(int z=0; z<2; z++) {
            for(int x=0; x<2; x++) {
                for(int y=0; y<2; y++) {
                    int nx = x + dx[k], ny = y + dy[k];
                    if((nx < 0 || nx >= 2 || ny < 0 || ny >= 2) && block[z][x][y]) {
                        ok = false;
                        continue;
                    }
                    else {
                        if(nx < 0 || nx >= 2 || ny < 0 || ny >= 2) continue;
                        n_block[z][nx][ny] = block[z][x][y];
                    }
                }
            }
        }

        if(ok) {
            Board n_board;
            int get_combo;
            tie(n_board, get_combo) = modify_board(board, n_block);
            ret = max(ret, dfs(n_board, blocks, idx+1, combo+get_combo));
        }
    }
    return ret;
}

int main() {
    while(cin >> H >> N, H || N) {
        Board board(30, vector< vector<int> >(2, vector<int>(2)));
        for(int i=0; i<H; i++) {
            for(int x=0; x<2; x++) {
                for(int y=0; y<2; y++) {
                    char c; cin >> c;
                    board[i][x][y] = (c == '#');
                }
            }
        }

        vector<Board> blocks(N, Board(2, vector< vector<int> >(2, vector<int>(2))));
        for(int i=0; i<N; i++) {
            for(int z=0; z<2; z++) {
                for(int x=0; x<2; x++) {
                    for(int y=0; y<2; y++) {
                        char c; cin >> c;
                        blocks[i][z][x][y] = (c == '#');
                    }
                }
            }
        }

        int ans = dfs(board, blocks, 0);
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 60
memory_kb: 3212
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;

int main()
{
	int H, N;
	while (cin >> H >> N, H | N) {
		vector<vector<string>> c(H + 10, vector<string>(2, string(2, '.')));
		vector<vector<vector<string>>> b(N, vector<vector<string>>(2, vector<string>(2)));
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 2; j++) {
				c[0][i][j] = '#';
			}
		}
		for (int i = 0; i < H; i++) {
			cin >> c[i + 1][0] >> c[i + 1][1];
		}
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < 2; j++) {
				for (int k = 0; k < 2; k++) {
					cin >> b[i][j][k];
				}
			}
		}
		int res = 0;
		int S = 1;
		for (int i = 0; i < N; i++) S *= 9;
		for (int s = 0; s < S; s++) {
			bool ok = true;
			int del = 0;
			int tmp = s;
			auto state = c;
			for (int i = 0; i < N; i++) {
				int dx = tmp % 3 - 1, dy = tmp / 3 % 3 - 1;
				for (int d = 0; d < 2; d++) {
					for (int x = 0; x < 2; x++) {
						for (int y = 0; y < 2; y++) {
							int tx = x + dx, ty = y + dy;
							if (b[i][d][x][y] == '#' && (tx < 0 || 2 <= tx || ty < 0 || 2 <= ty)) {
								ok = false;
								break;
							}
						}
					}
				}
				if (!ok) break;
				int h = H + 8;
				bool f = true;
				do {
					h--;
					for (int d = 0; d < 2; d++) {
						for (int x = 0; x < 2; x++) {
							for (int y = 0; y < 2; y++) {
								int tx = x + dx, ty = y + dy;
								if (b[i][d][x][y] == '#' && state[h + d][tx][ty] == '#') {
									f = false;
								}
							}
						}
					}
				} while (f);
				h++;
				for (int d = 0; d < 2; d++) {
					for (int x = 0; x < 2; x++) {
						for (int y = 0; y < 2; y++) {
							int tx = x + dx, ty = y + dy;
							if (b[i][d][x][y] == '#') {
								state[h + d][tx][ty] = '#';
							}
						}
					}
				}
				for (int d = 1, td = 1; d < H + 10; d++) {
					bool filled = true;
					for (int x = 0; x < 2; x++) {
						for (int y = 0; y < 2; y++) {
							if (state[d][x][y] != '#') {
								filled = false;
							}
						}
					}
					if (filled) {
						for (int x = 0; x < 2; x++) {
							for (int y = 0; y < 2; y++) {
								state[d][x][y] = '.';
							}
						}
						del++;
					}
					else {
						if (d != td) swap(state[d], state[td]);
						td++;
					}
				}
				tmp /= 9;
			}
			if (ok) res = max(res, del);
		}
		cout << res << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3176
final_rank: 7

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define rep(i,x,y) for(int i=(x); i < (y); i++)
#define debug(x) #x << "=" << (x)

#ifdef DEBUG
#define _GLIBCXX_DEBUG
#define print(x) std::cerr << debug(x) << " L:" << __LINE__ << ")" << std::endl;
#else
#define print(x)
#endif

const int inf=1e9;
const int64_t inf64=1e18;
const double eps=1e-9;

using i64=int64_t;

/*
vector<vector<vector<char>>> move_right(vector<vector<vector<char>>> v){
	vector<vector<vector<char>>> res(2,vector<vector<char>>(2,vector<char>(2,'.')));
	if(v.empty()){
		res.clear();
		return res;
	}

	rep(h,0,2) rep(y,0,2) if(v[h][1][y]=='#'){
		res.clear();
		return res;
	}

	rep(h,0,2) rep(y,0,2) res[h][1][y]=v[h][0][y];
	return res;
}

vector<vector<vector<char>>> move_up(vector<vector<vector<char>>> v){
	vector<vector<vector<char>>> res(2,vector<vector<char>>(2,vector<char>(2,'.')));
	if(v.empty()){
		res.clear();
		return res;
	}

	rep(h,0,2) rep(x,0,2) if(v[h][x][1]=='#'){
		res.clear();
		return res;
	}

	rep(h,0,2) rep(x,0,2) res[h][x][1]=v[h][x][0];
	return res;
}
*/

vector<vector<vector<char>>> move(vector<vector<vector<char>>> v,int dx,int dy){
	vector<vector<vector<char>>> res(2,vector<vector<char>>(2,vector<char>(2,'.')));
	if(v.empty()){
		res.clear();
		return res;
	}

	rep(h,0,2){
		rep(x,0,2){
			rep(y,0,2){
				int x1=x+dx,y1=y+dy;
				if(x1<0 or 2<=x1 or y1<0 or 2<=y1){
					if(v[h][x][y]=='#'){
						res.clear();
						return res;
					} 
				}else res[h][x1][y1]=v[h][x][y];
			}
		}
	}
	return res;
}

bool ok(vector<vector<vector<char>>>& c,vector<vector<vector<char>>>& v,int h){
	if(h<=-2) return false;
	rep(hd,0,2) rep(x,0,2) rep(y,0,2){
		if(v[hd][x][y]=='.') continue;
		if(h+hd<0) return false;
		else if(c[h+hd][x][y]=='#') return false;
	}
	return true;
}

vector<vector<vector<char>>> merge(vector<vector<vector<char>>>& c,vector<vector<vector<char>>>& v,int h){
	vector<vector<vector<char>>> nc=c;
	rep(hd,0,2) rep(x,0,2) rep(y,0,2){
		//assert(nc[h+hd][x][y]=='.' or v[hd][x][y]=='.');
		if(v[hd][x][y]=='#') nc[h+hd][x][y]='#';
	}
	return nc;
}

void shift(vector<vector<vector<char>>> &c,int h){
	rep(i,h,63){
		rep(x,0,2){
			rep(y,0,2){
				c[i][x][y]=c[i+1][x][y];
			}
		}
	}
	rep(x,0,2) rep(y,0,2) c[63][x][y]='.';
}

pair<int,vector<vector<vector<char>>>> erase(vector<vector<vector<char>>> &c){
	int cnt=0;
	auto nc=c;
	int top=-1;
	for(int h=63; h>=0; --h) rep(x,0,2) rep(y,0,2) if(nc[h][x][y]=='#'){
		top=h;
		goto A;
	}
	A:
	print(top);
	for(int h=top; h>=0; --h){
		bool f=true;
		rep(x,0,2) rep(y,0,2) if(nc[h][x][y]=='.'){
			f=false;
			break;
		}
		if(f){
			shift(nc,h);
			++cnt;
		}
	}
	return make_pair(cnt,nc);
}

void solve(int H,int N){
	vector<vector<vector<char>>> c(64,vector<vector<char>>(2,vector<char>(2,'.')));
	rep(h,0,H) rep(x,0,2) rep(y,0,2) cin >> c[h][x][y];
	vector<vector<vector<vector<char>>>> b(N,vector<vector<vector<char>>>(2,vector<vector<char>>(2,vector<char>(2,'.'))));
	rep(i,0,N){
		rep(h,0,2) rep(x,0,2) rep(y,0,2) cin >> b[i][h][x][y];
	}

	function<int(vector<vector<vector<char>>>&,int)> dfs=[&](vector<vector<vector<char>>>& c,int i){
		if(i==N) return 0;
		int res=0;
		rep(dx,-1,2){
			rep(dy,-1,2){
				auto nb=move(b[i],dx,dy);
				if(!nb.empty()){
					print(dx);
					print(dy);
					int h=32;
					assert(ok(c,nb,h));
					while(ok(c,nb,h)) --h;
					print(h);
					++h;
					assert(ok(c,nb,h));
					auto nc=merge(c,nb,h);
					/*
					rep(i,0,4){
						rep(x,0,2){
							rep(y,0,2){
								cerr << nc[i][x][y];
							}
							cerr << endl;
						}
						cerr << endl;
					}
					*/
					auto p=erase(nc);
					print(p.first);	
					/*
					rep(i,0,4){
						rep(x,0,2){
							rep(y,0,2){
								cerr << p.second[i][x][y];
							}
							cerr << endl;
						}
						cerr << endl;
					}
					*/
					res=max(res,p.first+dfs(p.second,i+1));
				}			
			}
		}
		/*
		{
			auto nb=b[i];
			if(!nb.empty()){
				int h=32;
				while(ok(c,nb,h)) --h;
				++h;
				auto nc=merge(c,nb,h);
				auto p=erase(nc);
				res=max(res,p.first+dfs(p.second,i+1));
			}	
		}
		{
			auto nb=move_right(b[i]);
			if(!nb.empty()){
				int h=32;
				while(ok(c,nb,h)) --h;
				++h;
				auto nc=merge(c,nb,h);
				auto p=erase(nc);
				res=max(res,p.first+dfs(p.second,i+1));
			}
		}
		{
			auto nb=move_up(b[i]);
			if(!nb.empty()){
				int h=32;
				while(ok(c,nb,h)) --h;
				++h;
				auto nc=merge(c,nb,h);
				auto p=erase(nc);
				res=max(res,p.first+dfs(p.second,i+1));
			}
		}
		{
			auto nb=move_up(move_right(b[i]));
			if(!nb.empty()){
				int h=32;
				while(ok(c,nb,h)) --h;
				++h;
				auto nc=merge(c,nb,h);
				auto p=erase(nc);
				res=max(res,p.first+dfs(p.second,i+1));
			}
		}
		*/
		return res;
	};

	cout << dfs(c,0) << endl;
}

int main() {
	std::cin.tie(0);
	std::ios::sync_with_stdio(false);
	cout.setf(ios::fixed);
	cout.precision(16);
	for(;;){
		int H,N;
		cin >> H >> N;
		if(H==0 and N==0) break;
		solve(H,N);
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3196
final_rank: 5

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps=1e-9;

//// < "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\a.txt" > "D:\D_Download\Visual Studio 2015\Projects\programing_contest_c++\Debug\b.answer"
int dx[] = { 0,0,0,1,1,1,-1,-1,-1 };
int dy[] = { -1,0,1,-1,0,1,-1,0,1 };
//50~
int main() {
	while (1) {
		int H, N; cin >> H >> N;
		if (!H)break;
		vector<vector<vector<int>>>field(30, vector<vector<int>>(2, vector<int>(2)));
		vector<vector<vector<vector<int>>>>blocks(N, vector<vector<vector<int>>>(2, vector<vector<int>>(2, vector<int>(2))));
		map<char, int>mp;
		mp['#'] = 1;
		mp['.'] = 0;
		for (int z = 0; z< H; ++z) {
			for (int y = 0; y < 2; ++y) {
				string st; cin >> st;
				for (int x = 0; x < 2; ++x) {
					field[z][y][x] = mp[st[x]];
				}
			}
		}
		for (int i = 0; i < N; ++i) {
			for (int z = 0; z < 2; ++z) {
				for (int y = 0; y < 2; ++y) {
					string st; cin >> st;
					for (int x = 0; x < 2; ++x) {
						blocks[i][z][y][x] = mp[st[x]];
					}
				}
			}
			bool flag = true;
			for (int y = 0; y < 2; ++y) {
				for (int x = 0; x < 2; ++x) {
					if (blocks[i][0][y][x])flag = false;
				}
			}
			if (flag) {
				for (int y = 0; y < 2; ++y) {
					for (int x = 0; x < 2; ++x) {
						blocks[i][0][y][x] = blocks[i][1][y][x];
						blocks[i][1][y][x] = 0;
					}
				}
			}
		}
		int amax = 1;
		for (int l = 0; l < N; ++l)amax *= 9;
		int ans = 0;
		for (int i = 0; i < amax; ++i) {
			bool ok = true;
			vector<vector<vector<int>>>nfield(field);
			int num(i);
			vector<int>a(3);
			int erase_num = 0;
			for (int j = 0; j < N; ++j) {
				const int way = num % 9;
				num /= 9;
				vector<vector<vector<int>>>nblock(2, vector<vector<int>>(2, vector<int>(2)));
				for (int z = 0; z < 2; ++z) {
					for (int y = 0; y < 2; ++y) {
						for (int x = 0; x < 2; ++x) {
							if (blocks[j][z][y][x]) {
								const int nz(z);
								const int ny(y + dy[way]);
								const int nx(x + dx[way]);
								if (ny < 0 || ny >= 2 || nx < 0 || nx >= 2) {
									ok = false;
									break;
								}
								nblock[nz][ny][nx] = true;
							}
						}
					}
				}
				if (!ok)break;
				int fallh = 0;
				for (int h = 20; h > 0; h--) {
					for (int z = 0; z < 2; ++z) {
						for (int y = 0; y < 2; ++y) {
							for (int x = 0; x < 2; ++x) {
								if (nblock[z][y][x]) {
									if (nfield[z + h - 1][y][x]) {
										fallh = h;
										break;
									}
								}
							}
						}
					}
					if (fallh)break;
				}
				for (int z = 0; z < 2; ++z) {
					for (int y = 0; y < 2; ++y) {
						for (int x = 0; x < 2; ++x) {
							if (nblock[z][y][x]&&nfield[z + fallh][y][x])assert(false);
							nfield[z + fallh][y][x] ^= nblock[z][y][x];
						}
					}
				}
				//?¶????
				{
					for (int z = 0; z < 30; ++z) {
						bool flag = true;
						for (int x = 0; x < 2; ++x) {
							for (int y = 0; y < 2; ++y) {
								if (!nfield[z][y][x]) {
									flag = false;
								}
							}
						}
						if (flag) {
							erase_num++;
							for (int x = 0; x < 2; ++x) {
								for (int y = 0; y < 2; ++y) {
									nfield[z][y][x] = 0;
								}
							}
						}
					}
				}

				for (int k = 0; k < 30; ++k) {
					for (int z = 0; z < 29; ++z) {
						bool flag = true;
						for (int x = 0; x < 2; ++x) {
							for (int y = 0; y < 2; ++y) {
								if (nfield[z][y][x]) {
									flag = false;
								}
							}
						}
						if (flag) {
							for (int x = 0; x < 2; ++x) {
								for (int y = 0; y < 2; ++y) {
									nfield[z][y][x] = nfield[z + 1][y][x];
								}
							}
						}
					}
				}

			}
			
			if (ok) {
				ans = max(ans, erase_num);
			}
		}
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 120
memory_kb: 3160
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;

int H,N,ans;
char t[4][4][30];
char u[4][4][30];
char v[4][4][30];
char p[3][2][2][2];

void init(){
  for(int i=0;i<4;i++)
    for(int j=0;j<4;j++)
      for(int k=0;k<30;k++){
        t[i][j][k]='.';
        if(i==0||j==0||k==29)t[i][j][k]='#';
        if(i==3||j==3)t[i][j][k]='#';
      }
}

bool check(int id,int x,int y,int z){
  if(z==29)return false;
  for(int i=0;i<2;i++){
    for(int j=0;j<2;j++){
      for(int k=0;k<2;k++){
        if(p[id][i][j][k]=='#'&&
           t[x+i][y+j][z+k]=='#')return false;
      }
    }
  }
  return true;
}

int dx[3],dy[3];

void solve(){
  for(int i=0;i<4;i++)
    for(int j=0;j<4;j++)
      for(int k=0;k<30;k++)
        t[i][j][k]=v[i][j][k];
  
  int cnt=0;
  for(int T=0;T<N;T++){
    if(!check(T,dx[T],dy[T],0))return;
    int H=0;
    while( check(T,dx[T],dy[T],H+1) )H++;
      
    for(int i=0;i<2;i++)
      for(int j=0;j<2;j++)
        for(int k=0;k<2;k++)
          if(p[T][i][j][k]=='#'){
            assert(t[dx[T]+i][dy[T]+j][H+k]=='.');
            t[dx[T]+i][dy[T]+j][H+k]=p[T][i][j][k];
          }
    
    for(int i=0;i<4;i++)
      for(int j=0;j<4;j++)
        for(int k=0;k<30;k++)
          u[i][j][k]=t[i][j][k];

    init();
    
    int C=28;
    for(int k=28;k>=0;k--){
      int count=0;
      for(int i=1;i<=2;i++)
        for(int j=1;j<=2;j++)
          if(u[i][j][k]=='#')count++;
      if(count==4){
        cnt++;
        continue;
      }
      for(int i=1;i<=2;i++)
        for(int j=1;j<=2;j++)
          t[i][j][C]=u[i][j][k];
      C--;
    }
  }

  ans=max(ans,cnt);

}

void dfs(int cnt){
  if(cnt==N){
    solve();
  }else{
    for(int i=0;i<3;i++){
      for(int j=0;j<3;j++){
        dx[cnt]=i;
        dy[cnt]=j;
        dfs(cnt+1);
      }
    }
  }
}

int main(){
  while(1){
    cin>>H>>N;
    if(H==0&&N==0)break;
    init();
    for(int k=28;k>28-H;k--)
      for(int i=1;i<=2;i++)
        for(int j=1;j<=2;j++)
          cin>>t[i][j][k];

    for(int a=0;a<N;a++){
      for(int k=0;k<2;k++)
        for(int i=0;i<2;i++)
          for(int j=0;j<2;j++)
            cin>>p[a][i][j][1-k];
    }
    for(int i=0;i<4;i++)
      for(int j=0;j<4;j++)
        for(int k=0;k<30;k++)
          v[i][j][k]=t[i][j][k];
    ans=0;
    dfs(0);
    cout<<ans<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1164
final_rank: 1