#include "bits/stdc++.h"
using namespace std;
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define rrep(i,a,b) for(int i=int(b) - 1;i>=(int)(a);i--)
const int INF = 0x3f3f3f3f;

using vc = vector<char>;
using vvc = vector<vc>;

vector<vvc> S;
vector<vector<vvc>> blocks;


void dump_impl(string s) {}
template <class H, class... T>
void dump_impl(string s, H head, T... tail) {
	int par = 0;
	rep(i, 0, s.size()) {
		char x = s[i];
		if (x == ',' && par == 0) {
			cerr << " = " << head << ", ";
			dump_impl(s.substr(i + 1), tail...);
			return;
		}
		else {
			cerr << x;
			if (x == '(') par++;
			if (x == ')') par--;
		}
	}
}
#define dump(...) 



int H, N;

int rec(int idx) {
	if (idx == N) {
		return 0;
	}

	auto check = [&](int dy, int dx) {
		rep(k, 0, 2) {
			rep(i, 0, 2) {
				rep(j, 0, 2) {
					int ii = i + dy;
					int jj = j + dx;
					if (blocks[idx][k][i][j] == '#') {
						if (ii < 0 || ii >= 2 || jj < 0 || jj >= 2) {
							return false;
						}
					}
				}
			}
		}
		return true;
	};

	auto intersect = [&](int dy, int dx, int y) {
		rep(k, 0, 2) {
			rep(i, 0, 2) {
				rep(j, 0, 2) {
					int ii = i + dy;
					int jj = j + dx;
					if (blocks[idx][k][i][j] == '#') {
						if (ii < 0 || ii >= 2 || jj < 0 || jj >= 2) {
							assert(false);
						}
						if (y + k < 0 || S[y + k][ii][jj] == '#') {
							dump(y + k, ii, jj);
							return true;
						}
					}
				}
			}
		}
		return false;
	};

	auto put_block = [&](int dy, int dx, int y) {
		rep(k, 0, 2) {
			rep(i, 0, 2) {
				rep(j, 0, 2) {
					int ii = i + dy;
					int jj = j + dx;
					if (blocks[idx][k][i][j] == '#') {
						if (ii < 0 || ii >= 2 || jj < 0 || jj >= 2) {
							assert(false);
						}
						if (y + k < 0 || S[y + k][ii][jj] == '#') {
							assert(false);
						}
						S[y + k][ii][jj] = '#';
					}
				}
			}
		}
	};

	auto remove_layer = [&]() {
		int ret = 0;
		vector<bool> to_remove(30, false);
		rep(k, 0, 30) {
			bool filled = true;
			rep(i, 0, 2) {
				rep(j, 0, 2) {
					if (S[k][i][j] == '.') {
						filled = false;
					}
				}
			}
			if (filled) {
				ret++;
				to_remove[k] = true;
			}
		}

		vector<vvc> nextS(30);
		rep(i, 0, 30) {
			nextS[i] = { {'.', '.'}, {'.', '.'} };
		}

		int nxt = 0;
		rep(k, 0, 30) {
			if (to_remove[k]) continue;
			nextS[nxt] = S[k];
			nxt++;
		}
		S = nextS;
		return ret;
	};

	int ret = 0;
	auto bkup = S;
	rep(dy, -1, 2) {
		rep(dx, -1, 2) {
			if (check(dy, dx)) {
				dump(idx, dy, dx);

				S = bkup;

				rrep(y, -1, 20) {
					if (intersect(dy, dx, y - 1)) {
						dump(y);
						put_block(dy, dx, y);
						break;
					}
				}
				
				int tmp = remove_layer();
				tmp += rec(idx + 1);
				ret = max(ret, tmp);
			}
		}
	}
	return ret;
}

int solve() {
	S.resize(30);
	rep(i, 0, 30) {
		S[i] = { {'.', '.'}, {'.', '.'} };
	}
	
	rep(k, 0, H) {
		vvc layer(2, vc(2));
		rep(i, 0, 2) rep(j, 0, 2) {
			cin >> layer[i][j];
		}
		S[k] = layer;
	}
	
	blocks.resize(N);
	rep(l, 0, N) {
		vector<vvc> b(2);
		rep(k, 0, 2) {
			vvc layer(2, vc(2));
			rep(i, 0, 2) rep(j, 0, 2) {
				cin >> layer[i][j];
			}
			b[k] = layer;
		}
		blocks[l] = b;
	}


	//cerr << "----" << endl;
	//rep(k, 0, 2) {
	//	rep(i, 0, 2) {
	//		rep(j, 0, 2) {
	//			cerr << S[k][i][j] << " ";
	//		}
	//		cerr << endl;
	//	}
	//	cerr << "----" << endl;
	//}

	return rec(0);
}

signed main() {
	while (1) {
		cin >> H >> N;
		if (H == 0 && N == 0) break;
		cout << solve() << endl;
	}
	return 0;
}
