#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;
}
