#include <bits/stdc++.h>
using namespace std;
#define FOR(i,k,n) for(int i = (int)(k); i < (int)(n); i++)
#define REP(i,n) FOR(i,0,n)
#define ALL(a) a.begin(), a.end()
#define MS(m,v) memset(m,v,sizeof(m))
typedef long long ll;
typedef long double ld;
typedef vector<int> vi;
typedef vector<string> vs;
typedef pair<int, int> pii;
const int MOD = 1000000007;
const int INF = MOD + 1;
const ld EPS = 1e-12;
template<class T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template<class T> T &chmax(T &a, const T &b) { return a = max(a, b); }

/*--------------------template--------------------*/


struct dan
{
	int state;
	dan(int n) :state(n) {}
	bool erase() { return state == 15; };
};

typedef pair<dan, dan> Block;


int h, n;
vector<dan> v;

int input()
{
	string s, t; cin >> s >> t;
	s += t;
	int res = 0;
	REP(i, 4) if (s[i] == '#') res |= 1 << i;
	return res;
}

vector<vi> make_move(int n)
{
	vector<vi> res;
	if (n == 1)
	{
		REP(i, 9) res.push_back(vi{ i });
	}
	if (n == 2)
	{
		REP(i, 9)REP(j, 9) res.push_back(vi{ i,j });
	}
	if (n == 3)
	{
		REP(i, 9)REP(j, 9)REP(k, 9) res.push_back(vi{ i,j,k });
	}
	return res;
}

int move(int n, int state)
{
	if (n == 0) //LU
	{
		if (state & 7) return -1;
		return state >> 3;
	}
	if (n == 1) //U
	{
		if (state & 3) return -1;
		return state >> 2;
	}
	if (n == 2) //RU
	{
		if (state & 11) return -1;
		return state >> 1;
	}
	if (n == 3) //L
	{
		if (state & 5) return -1;
		return state >> 1;
	}
	if (n == 4) return state;
	if (n == 5) //R
	{
		if (state & 10) return -1;
		return state << 1;
	}
	if (n == 6) //LD
	{
		if (state & 13) return -1;
		return state << 1;
	}
	if (n == 7) //D
	{
		if (state & 12) return -1;
		return state << 2;
	}
	if (n == 8) //RD
	{
		if (state & 14) return -1;
		return state << 3;
	}
}

bool check(Block b, int th)
{
	if (th < 0) return false;
	if (th >= v.size()) return true;
	if (v[th].state & b.first.state) return false;
	if (th + 1 >= v.size()) return true;
	if (v[th + 1].state & b.second.state) return false;
	return true;
}

void erase(int th)
{
	v[th].state = 0;
	for (int i = th; i < v.size() - 1; i++)
	{
		swap(v[i], v[i + 1]);
	}
}

int set_block(Block bl)
{
	int th = v.size();
	v.push_back(0); v.push_back(0);
	while (1)
	{
		if (!check(bl, th)) break;
		th--;
	}
	th++;
	assert((v[th].state & bl.first.state) == 0);
	assert((v[th + 1].state&bl.second.state) == 0);

	if(th>=0) v[th].state |= bl.first.state;
	v[th + 1].state |= bl.second.state;
	int res = 0;
	if (v[th + 1].erase())
	{
		res++;
		erase(th + 1);
	}
	if (th>= 0 && v[th].erase())
	{
		res++;
		erase(th);
	}
	return res;
}

int main()
{
	cin.sync_with_stdio(false); cout << fixed << setprecision(10);
	while (cin >> h >> n, h)
	{
		v.clear();
		vector<vi> move_pat = make_move(n);
		REP(i, h)
		{
			v.emplace_back(input());
		}
		vector<dan> drops;
		REP(i, n * 2)
		{
			drops.emplace_back(input());
			if (i % 2 && drops[drops.size() - 2].state == 0)
			{
				swap(drops[drops.size() - 2].state, drops[drops.size() - 1].state);
			}
		}
		int ans = 0;
		auto cp = v;
		REP(i, move_pat.size())
		{
			v = cp;
			int cnt = 0;
			REP(j, n)
			{
				dan a(drops[j * 2]), b(drops[j * 2 + 1]);
				a.state = move(move_pat[i][j], a.state);
				b.state = move(move_pat[i][j], b.state);
				if (a.state == -1 || b.state == -1)
				{
					cnt = 0;
					break;
				}
				cnt += set_block(Block(a, b));
			}
			chmax(ans, cnt);
		}
		cout << ans << endl;
	}
	
	return 0;
}