// #include <bits/stdc++.h>
#include <iostream>
#include <vector>
#include <string>
#include <cassert>
#include <cstring>
using namespace std;

#define DUMP(x) cerr << #x << "=" << x << endl
#define DUMP2(x, y) cerr<<"("<<#x<<", "<<#y<<") = ("<<x<<", "<<y<<")"<< endl
#define BINARY(x) static_cast<bitset<16> >(x)

#define rep(i,n) for(int i=0;i<(int)(n);i++)
#define REP(i,m,n) for (int i=m;i<(int)(n);i++)

#define in_range(x, y, w, h) (0<=(int)(x) && (int)(x)<(int)(w) && 0<=(int)(y) && (int)(y)<(int)(h))
#define ALL(a) (a).begin(),(a).end()

typedef long long ll;
const int INF = 1e9;
typedef pair<int, int> PII;
// int dx[4]={0, -1, 1, 0}, dy[4]={-1, 0, 0, 1};

struct Dan {
    bool block[2][2];
    Dan() {
        memset(block, 0, sizeof(block));
    }
};

int H, N;
vector<Dan> movableBlock;

void printBoard(vector<Dan> board)
{
    cerr << "=========" << endl;
    rep(i, board.size()) {
        cerr << "--------" << endl;
        rep(j, 2) {
            rep(k, 2) {
                cerr << board[i].block[j][k];
            }
            cerr << endl;
        }
    }
    cerr << "--------" << endl;
    cerr << "=========" << endl;
}


vector<Dan> move(vector<Dan> unmoveNowBlock, int dx, int dy)
{
    // ???????§????
    vector<Dan> nowBlock(2);
    rep(i, 2) {
        rep(y, 2) {
            rep(x, 2) {
                if (in_range(x-dx, y-dy, 2, 2)) {
                    nowBlock[i].block[y][x] = unmoveNowBlock[i].block[y-dy][x-dx];
                }
            }
        }
    }

    // cerr << "unmoveNowBlock;" << endl;
    // printBoard(unmoveNowBlock);
    // cerr << "nowBlock;" << endl;
    // printBoard(nowBlock);

    return nowBlock;
}


int solve(int n, vector<Dan> board, int score)
{
    if (n >= N) return score;

    vector<Dan> unmoveNowBlock(2);
    unmoveNowBlock[0] = movableBlock[2*n];
    unmoveNowBlock[1] = movableBlock[2*n+1];

    // cerr << "board :" << endl;
    // printBoard(board);

    // cerr << "unmoveNowBlock :" << endl;
    // printBoard(unmoveNowBlock);

    int res = 0;

    for (int dx = -1; dx <= 1; dx++) {
        for (int dy = -1; dy <= 1; dy++) {
            vector<Dan> nBoard = board;
            int nscore = score;

            bool ok = true;
            rep(z, 2) {
                rep(y, 2) {
                    rep(x, 2) { 
                        if (!in_range(x+dx, y+dy, 2, 2) && unmoveNowBlock[z].block[y][x]) ok = false;
                    }
                }
            }
            if (!ok) continue;

            vector<Dan> nowBlock = move(unmoveNowBlock, dx, dy);

            // ??????
            // rep(i, 2) {
            bool no_block = true;
            rep(i, 2) {
                rep(y, 2) {
                    rep(x, 2) {
                        if (nowBlock[i].block[y][x]) no_block = false;
                    }
                }
            }
            if (no_block) continue;

            int pos;
            for (pos = nBoard.size() - 2; pos>=-1; pos--) {
                rep(i, 2) {
                    rep(y, 2) {
                        rep(x, 2) {
                            if (nowBlock[i].block[y][x] && nBoard[pos+i].block[y][x]) {
                                pos++;
                                goto END_DROP;
                            }
                        }
                    }
                }
            }

        END_DROP:
            // DUMP(pos);

            rep(i, 2) {
                rep(y, 2) {
                    rep(x, 2) {
                        assert(!(nBoard[pos+i].block[y][x] && nowBlock[i].block[y][x]));
                        nBoard[pos+i].block[y][x] |= nowBlock[i].block[y][x];
                    }
                }
            }

            // cerr << "Dropped" << endl;
            // printBoard(nBoard);

            // ?¶????
            for (int i=nBoard.size() - 1; i>=1; i--) {
                bool ok = true;
                rep(y, 2) {
                    rep(x, 2) {
                        if (!nBoard[i].block[y][x]) ok = false;
                    }
                }
                if (ok) {
                    nBoard.erase(nBoard.begin() + i);
                    nscore++;
                }
            }

            // cerr << "Erased" << endl;
            // printBoard(nBoard);

            // ?¬????????????????
            res = max(res, solve(n+1, nBoard, nscore));
        }
    }

    return res;
}


int main()
{
    while (cin >> H >> N, H || N) {
        vector<Dan> board(H+1+2*N);
        movableBlock.resize(2*N);

        Dan tmp;
        rep(i, 2) rep(j, 2) tmp.block[i][j] = true;
        board[0] = tmp;
        
        for (int i=H+1; i<H+1+2*N; i++) {
            memset(board[i].block, 0, sizeof(board[i].block));
        }

        for (int i=1; i<=H; i++) {
            rep(j, 2) {
                string S;
                cin >> S;
                rep(k, 2) {
                    board[i].block[j][k] = (S[k] == '#');
                }
            }
        }

        rep(i, 2*N) {
            rep(j, 2) {
                string S;
                cin >> S;
                rep(k, 2) {
                    movableBlock[i].block[j][k] = (S[k] == '#');
                }
            } 
        }

        cout << solve(0, board, 0) << endl;
    }
}

Measured memory_bytes: 3152