Topics

Input:
3
3 4 3
4 2 1
3 1 3

Output:
*****************
*\..*../*\..*../*
*.\.*./.*.\.*./.*
*..\*/..*..\*/..*
*****************
*../*\..*../*\..*
*./.*.\.*./.*.\.*
*/..*..\*/..*..\*
*****************
*\..*../*\..*../*
*.\.*./.*.\.*./.*
*..\*/..*..\*/..*
*****************

*****
*\*/*
*****
*/*\*
*****
*\*/*
*****
*/*\*
*****

*****
*\..*
*.\.*
*..\*
*****
*../*
*./.*
*/..*
*****
*\..*
*.\.*
*..\*
*****

Idea

The overall grid dimensions can be computed as:

The extra row and column come from the fact that every cell contributes its bottom and right boundaries, and the grid has an initial top and left border.

Drawing the Borders

Any row or column that corresponds to a boundary is printed as a line of * characters. In particular, for every coordinate we print a border character if:

This neatly partitions the grid into cells of size .

Drawing the Interior Pattern

Modulo arithmetic is used to determine the periodicity of the pattern

For the positions that lie inside the cells (i.e. not on the borders), the pattern is determined by the following rules:

  • Backslash Pattern: Print a backslash \ if
  • Forward Slash Pattern: Print a forward slash / if
  • Otherwise: Print a dot .

Note that classic diagonal conditions are: and respectively. The mod helps us deal with the periodicity. We can observe that the diagonals repeat after certain intervals and derive a relation analytically.

Code

void print(int i, int j, int p) {
  if (i % (p + 1) == 0 or j % (p + 1) == 0) {
    cout << "*";
  } else if ((i - j) % (2 * (p + 1)) == 0) {
    cout << "\\";
  } else if ((i + j) % (2 * (p + 1)) == 0) {
    cout << "/";
  }
  else
    cout << ".";
}
 
void solve() {
  int n, m, p;
  cin >> n >> m >> p;
 
  int rows, cols;
  rows = n * (p + 1) + 1;
  cols = m * (p + 1) + 1;
 
  for (int i = 0; i < rows; ++i) {
    for (int j = 0; j < cols; ++j) {
      print(i, j, p);
    }
    cout << endl;
  }
}