#include "testlib.h"

const int MAXT = 250'000;
const int MAXSUM = 1'000'000;

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

using Field = std::vector<std::string>;

Field generate(int n, int m, int x1, int y1, int x2, int y2, int mask) {
	Field a(n);
	for (int i = 0; i < n; ++i) {
		a[i].resize(m, '.');
	}

	for (int id = 0; id < n * m; ++id) {
		if (((mask >> id) & 1) == 1) {
			int i = id / m;
			int j = id % m;
			a[i][j] = '#';
		}
	}
	a[x1][y1] = 's';
	a[x2][y2] = 'f';

	return a;
}

bool check(const Field& f, int n, int m, int x1, int y1, int x2, int y2) {
	std::vector<std::vector<bool>> used(n, std::vector<bool>(m));

	auto dfs = [&f, &used, &n, &m](auto self, int x, int y) -> void {
		used[x][y] = true;

		for (int i = 0; i < 4; ++i) {
			int newX = x + dx[i];
			int newY = y + dy[i];

			if (newX < 0 || newY < 0 || newX >= n || newY >= m) {
				continue;
			}
			if (used[newX][newY] || f[newX][newY] == '#') {
				continue;
			}

			self(self, newX, newY);
		}
	};
	dfs(dfs, x1, y1);

	return used[x2][y2];
}

int main(int argc, char** argv) {
  registerGen(argc, argv, 1);

  int t = opt<int>("t");
  int minn = opt<int>("minn");
  int maxn = opt<int>("maxn");
  int maxsum = opt<int>("maxsum");

  auto ns = rnd.partition(t, maxsum, minn);
    
  std::cout << t << '\n';
  for (int q = 0; q < t; q++) {
    int area = 2 * ns[q];
    std::vector<std::pair<int, int>> options;
    while (true) {
      for (int n = 2; n <= maxn; n++) {
        if (area % n == 0 && area / n >= 2 && area / n <= maxn) {
          options.emplace_back(n, area / n);
        }
      }
      if (!options.empty()) {
        break;
      }
      area -= 2;
    }
    int option_id = rnd.next(int(options.size()));
    auto [n, m] = options[option_id];
    Field f;
    while (true) {
      f = Field(n, std::string(m, '.'));
      int p = rnd.next(0, 100);
      std::vector<std::pair<int, int>> empty;
      for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
          f[i][j] = (rnd.next(100) < p ? '#' : '.');
          if (f[i][j] == '.') {
            empty.emplace_back(i, j);
          }
        }
      }
      if (empty.size() >= 2) {
        int i, j;
        do {
          i = rnd.next(int(empty.size()));
          j = rnd.next(int(empty.size()));
        } while (i == j);
        auto [x1, y1] = empty[i];
        auto [x2, y2] = empty[j];
        f[x1][y1] = 's';
        f[x2][y2] = 'f';
        if (check(f, n, m, x1, y1, x2, y2)) {
          break;
        }
      }
    }
    std::cout << n << " " << m << '\n';
    for (int i = 0; i < n; i++) {
      std::cout << f[i] << '\n';
    }
  }

  return 0;
}