This task is based on    Kronecker product   of two matrices.

If your language has no a built-in function for such product then you need to implement it first.

The essence of fractals is self-replication (at least, self-similar replications).

So, using   n   times self-product of the matrix   (filled with 0/1)   we will have a fractal of the   nth   order.

Actually, "self-product" is a Kronecker power of the matrix.

In other words: for a matrix   M   and a power   n   create a function like   matkronpow(M, n),

which returns   MxMxMx...   (n   times product).

A formal recurrent algorithm of creating Kronecker power of a matrix is the following:



Algorithm


Let M is an initial matrix, and Rn is a resultant block matrix of the Kronecker power, where n is the power (a.k.a. order).
Self-product of M, i.e., M x M producing R2 (resultant matrix with order/power 2).
To receive the next order/power matrix use this recurrent formula: Rn = R(n-1) x M.
Plot this Rn matrix to produce the nth order fractal.



Even just looking at the resultant matrix you can see what will be plotted.

There are virtually infinitely many fractals of this type. You are limited only by your creativity and
the power of your computer.



Task

Using  Kronecker product implement and show two popular and well-known fractals, i.e.:

  Vicsek fractal;
  Sierpinski carpet fractal.


The last one ( Sierpinski carpet) is already here on RC, but built using different approaches.




Test cases

These 2 fractals (each order/power 4 at least) should be built using the following 2 simple matrices:

          │ 0 1 0 │    and    │ 1 1 1 │
          │ 1 1 1 │           │ 1 0 1 │
          │ 0 1 0 │           │ 1 1 1 │

Note

 Output could be a graphical or ASCII-art representation, but if an order is set > 4 then printing is not suitable.
 The orientation and distortion of the fractal could be your language/tool specific.
 It would be nice to see one additional fractal of your choice, e.g., based on using a single (double) letter(s) of an alphabet, any sign(s) or already made a resultant matrix of the Kronecker product.


See implementations and results below in JavaScript, PARI/GP and R languages. They have additional samples of "H", "+" and checkerboard fractals.




 
package kronecker;
 
/**
 * Uses the Kronecker product powers of two rectangular matrices
 * to generate fractals and tests it with three examples.
 */
public class ProductFractals {
  /**
   * Find the Kronecker product of the arguments.
   * @param a The first matrix to multiply.
   * @param b The second matrix to multiply.
   * @return A new matrix: the Kronecker product of the arguments.
   */
  public static int[][] product(final int[][] a, final int[][] b) {
    // Create matrix c as the matrix to fill and return.
    // The length of a matrix is its number of rows.
    final int[][] c = new int[a.length*b.length][];
    // Fill in the (empty) rows of c.
    // The length of each row is the number of columns.
    for (int ix = 0; ix < c.length; ix++) {
      final int num_cols = a[0].length*b[0].length;
      c[ix] = new int[num_cols];
    }
    // Now fill in the values: the products of each pair.
    // Go through all the elements of a.
    for (int ia = 0; ia < a.length; ia++) {
      for (int ja = 0; ja < a[ia].length; ja++) {
        // For each element of a, multiply it by all the elements of b.
        for (int ib = 0; ib < b.length; ib++) {
          for (int jb = 0; jb < b[ib].length; jb++) {
             c[b.length*ia+ib][b[ib].length*ja+jb] = a[ia][ja] * b[ib][jb];
          }
        }
      }
    }
 
    // Return the completed product matrix c.
    return c;
  }
 
  /**
   * Print an image obtained from an integer matrix, using the specified
   * characters to indicate non-zero and zero elements.
   * @param m The matrix to print.
   * @param nz The character to print for a non-zero element.
   * @param z The character to print for a zero element.
   */
  public static void show_matrix(final int[][] m, final char nz, final char z) {
    for (int im = 0; im < m.length; im++) {
      for (int jm = 0; jm < m[im].length; jm++) {
        System.out.print(m[im][jm] == 0 ? z : nz);
      }
      System.out.println();
    }
  }
 
  /**
   * Compute the specified Kronecker product power
   * of the matrix and return  it.
   * @param m The matrix to raise to the power.
   * @param n The power to which to raise the matrix.
   * @return A new matrix containing the resulting power.
   */
  public static int[][] power(final int[][] m, final int n) {
    // Start with m itself as the first power.
    int[][] m_pow = m;
    // Start the iteration with 1, not 0,
    // since we already have the first power.
    for (int ix = 1; ix < n; ix++) {
      m_pow = product(m, m_pow);
    }
    return m_pow;
  }
 
  /**
   * Run a test by computing the specified Kronecker product power
   * of the matrix and printing matrix and power.
   * @param m The base matrix raise to the power.
   * @param n The power to which to raise the matrix.
   */
  private static void test(final int[][] m, final int n) {
    System.out.println("Test matrix");
    show_matrix(m, '*', ' ');
    final int[][] m_pow = power(m, n);
    System.out.println("Matrix power " + n);
    show_matrix(m_pow, '*', ' ');
  }
 
  /**
   * Create the matrix for the first test and run the test.
   */
  private static void test1() {
    // Create the matrix.
    final int[][] m = {{0, 1, 0},
                       {1, 1, 1},
                       {0, 1, 0}};
    // Run the test.
    test(m, 4);
  }
 
  /**
   * Create the matrix for the second test and run the test.
   */
  private static void test2() {
    // Create the matrix.
    final int[][] m = {{1, 1, 1},
                       {1, 0, 1},
                       {1, 1, 1}};
    // Run the test.
    test(m, 4);
  }
 
  /**
   * Create the matrix for the second test and run the test.
   */
  private static void test3() {
    // Create the matrix.
    final int[][] m = {{1, 0, 1},
                       {1, 0, 1},
                       {0, 1, 0}};
    // Run the test.
    test(m, 4);
  }
 
  /**
   * Run the program to run the three tests.
   * @param args Command line arguments (not used).
   */
  public static void main(final String[] args) {
    // Test the product fractals.
    test1();
    test2();
    test3();
  }
 
}
 