#include <bits/stdc++.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=int(a)-1;i>=int(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)

#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define getidx(ary,key) lower_bound(_all(ary),key)-begin(ary)
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))
#define popcount(n) (__builtin_popcountll(n))

using namespace std;

template<class T>bool chmax(T &a, const T &b) { return (a < b) ? (a = b, 1) : 0;}
template<class T>bool chmin(T &a, const T &b) { return (b < a) ? (a = b, 1) : 0;}

using ll = long long;
using R = long double;
const R EPS = 1e-9L; // [-1000,1000]->EPS=1e-8 [-10000,10000]->EPS=1e-7
inline int sgn(const R& r) {return (r > EPS) - (r < -EPS);}
inline R sq(R x) {return sqrt(max(x, 0.0L));}

const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

// Problem Specific Parameter:

// Description: 素集合を管理するデータ構造
// TimeComplexity: 初期化$\mathcal{O}(n)$ 更新$\mathcal{O}(\log n)$
// Verifyed: AOJ DSL_1_A

struct Union_find {
	Union_find(int n) {data.assign(n, -1);}
	int find(int x) {return (data[x] < 0) ? x : data[x] = find(data[x]);}
	void unite(int a, int b) {
		a = find(a), b = find(b);
		if (a != b) {
			if (data[a] < data[b]) swap(a, b);
			data[a] += data[b], data[b] = a;
		}
	}
	bool same(int a, int b) {return find(a) == find(b);}
	int size(int x) {return -data[x];}
	vector<int> data;
};

int h, w;
char ans[210][210];



void making(int a, int b) {
	int cur = 0;
	int val = 0;
	h = 0, w = 100;

	while (cur < b) {
		cur += w / 2;
		rep(j, w) {
			rep(i, h, h + 4) {
				if ((j + val) & 1) {
					ans[i][j] = '#';
				} else {
					ans[i][j] = '.';
				}
			}
		}

		h += 4;
		val ^= 1;
	}

	// black
	const int num = cur - b + 1;
	rep(j, num) ans[0][2 * j] = '#';

	// white
	int rest = cur - a;

	int i = 4;

	if(rest == 0) return;

	if (h != 4) {
		for (int j = 0; j < w - 1; ++j) {
			if (ans[i - 1][j] == '#') {
				ans[i - 1][j] = '.';
			}

			if (ans[i][j] == '#') {
				ans[i][j] = '.';
			}
			rest--;
			if (rest == 0) return;
		}
		i += 4;
	} else {
		for (int j = 1; j < w; j += 2) {
			if (ans[i - 1][j] == '#') {
				ans[i - 1][j] = '.';
			}

			if (ans[i][j] == '#') {
				ans[i][j] = '.';
			}
			rest--;
			if (rest == 0) return;
		}
	}



	for (; i <= h; i += 4) {
		for (int j = 0; j < w; j += 2) {
			if (ans[i - 1][j] == '#') {
				ans[i - 1][j] = '.';
			}

			if (ans[i][j] == '#') {
				ans[i][j] = '.';
			}
			rest--;
			if (rest == 0) return;
		}
	}



}

int main(void) {
	int a, b;
	cin >> a >> b;

	bool flag = false;
	if (a > b) {
		flag = true;
		swap(a, b);
	}

	/*
	for (int a = 1; a <= 500; ++a) {
		for (int b = a; b <= 500; ++b) {
			cerr << a << " " << b << endl;
			making(a, b);

			Union_find uf(h * w);
			rep(i, h)rep(j, w) {
				if (i - 1 >= 0 and ans[i][j] == ans[i - 1][j]) uf.unite(w * (i - 1) + j, w * i + j);
				if (j - 1 >= 0 and ans[i][j] == ans[i ][j - 1]) uf.unite(w * i + j - 1, w * i + j);

			}

			int na = 0, nb = 0;

			rep(i, h)rep(j, w) {
				if (uf.find(w * i + j) == w * i + j) {
					if (ans[i][j] == '.')
						na++;
					else
						nb++;
				}
			}

			assert(na == a and nb == b);
		}
	}
	*/
	making(a,b);

	if (flag) {
		rep(i, h)rep(j, w) {
			ans[i][j] ^= ('#'^'.');
		}
	}

	cout << h << " " << w << endl;
	rep(i, h) {
		rep(j, w) cout << ans[i][j];
		cout << endl;
	}

	return 0;
}



Measured memory_bytes: 256