import std.stdio;
import std.algorithm;
import std.string;

void main() {
    while (true) {
        int H, N;
        scanf("%d %d\n", &H, &N);
        if (H == 0 && N == 0) break;
        const int X = 20;
        auto F = new string[2][X];

        foreach (i; 0 .. H) {
            F[i][0] = readln.chomp;
            F[i][1] = readln.chomp;
        }
        foreach (i; H .. X) foreach (j; 0 .. 2) F[i][j] = "..";
        int c = H;

        struct S {
            string[2][] F;
            int del_n;
        }
        S[] states = [S(F, 0)];
        foreach (n; 0 .. N) {
            string[2][2] block;
            foreach (i; 0 .. 2) foreach (j; 0 .. 2) {
                block[i][j] = readln.chomp; // which comes first is the lower one
            }
            bool empty(string[2] f) {
                foreach (i; 0 .. 2) foreach (j; 0 .. 2) if (f[i][j] == '#') return false;
                return true;
            }
            if (empty(block[0])) {
                swap(block[0], block[1]);
            }

            S[] nstates;
            for (int dy = -1; dy <= 1; dy++) {
                for (int dx = -1; dx <= 1; dx++) {
                    char[][2][2] nblock;
                    foreach (i; 0 .. 2) foreach (j; 0 .. 2) {
                        nblock[i][j] = new char[2];
                        foreach (k; 0 .. 2) {
                            nblock[i][j][k] = '.';
                        }
                    }

                    foreach (k; 0 .. 2) {
                        foreach (i; 0 .. 2) {
                            foreach (j; 0 .. 2) {
                                if (block[k][i][j] == '#' && (i + dy < 0 || i + dy >= 2 || j + dx < 0 || j + dx >= 2)) {
                                    goto next;
                                }
                            }
                        }
                    }

                    // this block can be slided by [dy, dx]
                    foreach (k; 0 .. 2) foreach (i; 0 .. 2) foreach (j; 0 .. 2) {
                        if (block[k][i][j] == '#') {
                            nblock[k][i + dy][j + dx] = '#'; // this line cannot cause range violation
                        }
                    }

                    foreach (s; states) {
                        S drop() {
                            auto F = s.F.dup;
                            int del_n = s.del_n;
                            int h = 0;

                            bool collide(string[2] f, string[2] g) {
                                foreach (i; 0 .. 2) foreach (j; 0 .. 2) {
                                    if (f[i][j] == '#' && g[i][j] == '#') return true;
                                }
                                return false;
                            }
                            string[2] merge(string[2] f, string[2] g) {
                                assert(!collide(f, g));
                                char[2][2] r;
                                foreach (i; 0 .. 2) foreach (j; 0 .. 2) {
                                    r[i][j] = ((f[i][j] == '#' || g[i][j] == '#') ? '#' : '.');
                                }
                                string[2] ret;
                                foreach (i; 0 .. 2) ret[i] = r[i].idup;
                                return ret;
                            }

                            for (int y = X - 2; y >= 0; y--) {
                                if (collide(F[y], cast(string[2])nblock[0]) || collide(F[y + 1], cast(string[2])nblock[1])) {
                                    h = y + 1;
                                    break;
                                }
                            }
                            foreach (i; 0 .. 2) {
                                F[h + i] = merge(F[h + i], cast(string[2])nblock[i]);
                            }
                            int c_height = 0;
                            foreach (y; 0 .. X) {
                                bool filled(string[2] f) {
                                    foreach (i; 0 .. 2) foreach (j; 0 .. 2)
                                        if (f[i][j] == '.') return false;
                                    return true;
                                }
                                if (filled(F[y])) {
                                    del_n++;
                                } else {
                                    F[c_height] = F[y];
                                    c_height++;
                                }
                            }
                            foreach (y; c_height .. X) {
                                F[y] = ["..", ".."];
                            }
                            return S(F, del_n);
                        }
                        auto nstate = drop();
                        nstates ~= nstate;
                    }
                    next:;
                }
            }
            states = nstates;
        }
        
        int ans = 0;
        foreach (state; states) {
            ans = max(ans, state.del_n);
        }

        writeln(ans);
    }
}

Measured memory_bytes: 3140