Kronecker product based fractals

From Rosetta Code
Task
Kronecker product based fractals
You are encouraged to solve this task according to the task description, using any language you may know.

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 n-th order.
Even just looking at the resultant matrix you can see it.
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.:


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

Test cases

These 2 fractals (order 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 alredy 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.

gnuplot[edit]

File for the load command is the only possible imitation of the fine function in the gnuplot.

Note
  • Find plotff.gp here on RC
  • dat-files are PARI/GP generated output files. They are too big to post them here on RC.


Works with: gnuplot version 5.0 (patchlevel 3) and above
File:Pkf1.png
Output pkf1.png
File:Pkf2.png
Output pkf2.png
File:Pkf3.png
Output pkf3.png
 
## KPF.gp 4/8/17 aev
## Plotting 3 KPF pictures.
## dat-files are PARI/GP generated output files:
#cd 'C:\gnupData'
 
##PKF1 from PARI/GP created file pkf1.dat
ttl = "Vicsec fractal"; clr = '"blue"'; filename = "pkf1";
load "plotff.gp"
 
##PKF2 from PARI/GP created file pkf2.dat
ttl = "Sierpinski carpet fractal"; clr = '"navy"';filename = "pkf2";
load "plotff.gp"
 
##PKF3 from PARI/GP created file pkf3.dat
ttl = "Sierpinski triangle fractal"; clr = '"dark-green"'; filename = "pkf3";
load "plotff.gp"
 
Output:
3 plotted files: pkf1.png, pkf2.png and pkf3.png.

Haskell[edit]

Works with: Chrome and Firefox

This implementation compiles to javascript that runs in the browser using the ghcjs compiler . The reflex-dom library is used to help with svg rendering.

{-# LANGUAGE OverloadedStrings #-}
import Reflex
import Reflex.Dom
import Data.Map as DM (Map, fromList)
import Data.Text (Text, pack)
import Data.List (transpose)
 
-- Show Vicsek and Sierpinski Carpet fractals
main :: IO ()
main = mainWidget $ do
elAttr "h1" ("style" =: "color:black") $ text "Kroneker Product Based Fractals"
elAttr "a" ("href" =: "http://rosettacode.org/wiki/Kronecker_product_based_fractals#Haskell") $ text "Rosetta Code / Kroneker product based fractals / Haskell"
 
-- Show a Vicsek fractal
el "br" $ return ()
elAttr "h2" ("style" =: "color:brown") $ text "Vicsek Fractal"
showFractal [[0, 1, 0] ,[1, 1, 1] ,[0, 1, 0] ]
 
-- Show a Sierpinski Carpet fractal
el "br" $ return ()
elAttr "h2" ("style" =: "color:brown") $ text "Sierpinski Carpet Fractal"
showFractal [[1, 1, 1] ,[1, 0, 1] ,[1, 1, 1] ]
 
-- Size in pixels of an individual cell
cellSize :: Int
cellSize = 8
 
-- Given a "seed" matrix, generate and display a fractal.
showFractal :: MonadWidget t m => [[Int]] -> m ()
showFractal seed = do
let boardAttrs w h =
fromList [ ("width" , pack $ show $ w * cellSize)
, ("height", pack $ show $ h * cellSize)
]
fractals = iterate (kronekerProduct seed) seed
shown = fractals !! 3 -- the fourth fractal (starting from 0)
w = length $ head shown
h = length shown
elSvgns "svg" (constDyn $ boardAttrs w h) $ showMatrix shown
 
-- Compute the Kroneker product of two matrices.
kronekerProduct :: Num a => [[a]] -> [[a]] -> [[a]]
kronekerProduct xs ys =
let m0 = flip $ fmap.fmap.(*)
m1 = flip $ fmap.fmap.m0
in concat $ fmap (fmap concat.transpose) $ m1 xs ys
 
-- Show an entire matrix
showMatrix :: MonadWidget t m => [[Int]] -> m ()
showMatrix m = mapM_ showRow $ zip [0..] m
 
-- Show a single horizontal row of a matrix
showRow :: MonadWidget t m => (Int,[Int]) -> m ()
showRow (x,r) = mapM_ (showCell x) $ zip [0..] r
 
-- Show a circle in a box moved to the correct location on screen
showCell :: MonadWidget t m => Int -> (Int,Int) -> m ()
showCell x (y,on) =
let boxAttrs (x,y) = -- Place box on screen
fromList [ ("transform",
pack $ "scale (" ++ show cellSize ++ ", " ++ show cellSize ++ ") "
++ "translate (" ++ show x ++ ", " ++ show y ++ ")"
)
]
 
cellAttrs = -- Draw circle in box.
fromList [ ( "cx", "0.5")
, ( "cy", "0.5")
, ( "r", "0.45")
, ( "style", "fill:green")
]
 
in if (on==1) then -- Only draw circle for elements containing 1
elSvgns "g" (constDyn $ boxAttrs (x,y)) $
elSvgns "circle" (constDyn $ cellAttrs) $
return ()
else
return ()
 
-- Wrapper around elDynAttrNS'
elSvgns :: MonadWidget t m => Text -> Dynamic t (Map Text Text) -> m a -> m a
elSvgns t m ma = do
(el, val) <- elDynAttrNS' (Just "http://www.w3.org/2000/svg") t m ma
return val

Link to live demo: https://dc25.github.io/rosettaCode__Kronecker_product_based_fractals/ ( a little slow to load ).

JavaScript[edit]

Using Version #1 of Kronecker product in JavaScript.

Works with: Chrome
File:VicsekFractaljs.png
Output VicsekFractaljs.png
File:SierpCarpetFractaljs.png
Output SierpCarpetFractaljs.png
File:CheckbrdFractaljs.png
Output CheckbrdFractaljs.png
 
// KPF.js 6/23/16 aev
// HFJS: Plot any matrix mat (filled with 0,1)
function pmat01(mat, color) {
// DCLs
var cvs = document.getElementById('canvId');
var ctx = cvs.getContext("2d");
var w = cvs.width; var h = cvs.height;
var m = mat[0].length; var n = mat.length;
// Cleaning canvas and setting plotting color
ctx.fillStyle="white"; ctx.fillRect(0,0,w,h);
ctx.fillStyle=color;
// MAIN LOOP
for(var i=0; i<m; i++) {
for(var j=0; j<n; j++) {
if(mat[i][j]==1) { ctx.fillRect(i,j,1,1)};
}//fend j
}//fend i
}//func end
// Prime functions:
// Create Kronecker product based fractal matrix rm from matrix m (order=ord)
function ckpbfmat(m,ord) {
var rm=m;
for(var i=1; i<ord; i++) {rm=mkp(rm,m)};
//matpp2doc('R 4 ordd',rm,'*'); // ASCII "plotting" - if you wish to try.
return(rm);
}
// Create and plot Kronecker product based fractal from matrix m (filled with 0/1)
function cpmat(m,ord,color) {
var kpr;
kpr=ckpbfmat(m,ord);
pmat01(kpr,color);
}
// Fractal matrix "pretty" printing to document.
// mat should be filled with 0 and 1; chr is a char substituting 1.
function matpp2doc(title,mat,chr) {
var i,j,re='',e; var m=mat.length; var n=mat[0].length;
document.write('&nbsp;&nbsp;<b>'+title+'</b>:<pre>');
for(var i=0; i<m; i++) {
for(var j=0; j<n; j++) {
e='&nbsp;'; if(mat[i][j]==1) {e=chr}; re+=e;
}//fend j
document.write('&nbsp;&nbsp;'+re+'<br />'); re='';
}//fend i
document.write('</pre>');
}
// mkp function (exotic arrow function): Return the Kronecker product
// of the a and b matrices
mkp=(a,b)=>a.map(a=>b.map(b=>a.map(y=>b.map(x=>r.push(y*x)),t.push(r=[]))),t=[])&&t;
 
Required tests
 
<!-- VicsekFractal.html -->
<html>
<head>
<title>Vicsek fractal</title>
<script src="KPF.js"></script>
</head>
<body onload="cpmat([[0,1,0],[1,1,1],[0,1,0]],6,'navy')">
<h3>Vicsek fractal</h3>
<a href="SierpCarpetFractal.html"> Next: Sierpinski carpet fractal</a><br />
<canvas id="canvId" width="750" height="750" style="border: 1px outset;"></canvas>
</body></html>
 
 
<!-- SierpCarpetFractal.html -->
<html>
<head>
<title>Sierpinski carpet fractal</title>
<script src="KPF.js"></script>
</head>
<body onload="cpmat([[1,1,1],[1,0,1],[1,1,1]],6,'brown')">
<h3>Sierpinski carpet fractal</h3>
<a href="Checkerboard.html"/> Next: Checkerboard </a><br />
<canvas id="canvId" width="750" height="750" style="border: 1px outset;"></canvas>
</body></html>
 
<lang html>
<!-- Checkerboard.html -->
<html>
<head>
<title>Checkerboard</title>
<script src="KPF.js"></script>
</head>
<body onload="cpmat([[0,1,0,1],[1,0,1,0],[0,1,0,1],[1,0,1,0]],5,'black')">
<h3>Checkerboard</h3>
<a href="VicsekFractal.html"/> Next: Vicsek fractal </a><br />
<canvas id="canvId" width="750" height="750" style="border: 1px outset;"></canvas>
</body></html>
 
Output:
Page VicsekFractal.html with VicsekFractaljs.png
Page SierpCarpetFractal.html with SierpCarpetFractaljs.png
Page Checkerboard.html with CheckbrdFractaljs.png

Lua[edit]

Needs LÖVE 2D Engine

 
function prod( a, b )
local rt, l = {}, 1
for m = 1, #a do
for p = 1, #b do
rt[l] = {}
for n = 1, #a[m] do
for q = 1, #b[p] do
table.insert( rt[l], a[m][n] * b[p][q] )
end
end
l = l + 1
end
end
return rt
end
function love.load()
wid, hei = love.graphics.getWidth(), love.graphics.getHeight()
canvas = love.graphics.newCanvas( wid, hei )
mA = { {0,1,0}, {1,1,1}, {0,1,0} }; mB = { {1,0,1}, {0,1,0}, {1,0,1} }
mC = { {1,1,1}, {1,0,1}, {1,1,1} }; mD = { {1,1,1}, {0,1,0}, {1,1,1} }
end
function drawFractals( m )
love.graphics.setCanvas( canvas )
love.graphics.clear()
love.graphics.setColor( 255, 255, 255 )
for j = 1, #m do
for i = 1, #m[j] do
if m[i][j] == 1 then
love.graphics.points( i * .1, j * .1 )
end
end
end
love.graphics.setCanvas()
end
function love.keypressed( key, scancode, isrepeat )
local t = {}
if key == "a" then
print( "Build Vicsek fractal I" ); t = mA
elseif key == "b" then
print( "Build Vicsek fractal II" ); t = mB
elseif key == "c" then
print( "Sierpinski carpet fractal" ); t = mC
elseif key == "d" then
print( "Build 'H' fractal" ); t = mD
else return
end
for i = 1, 3 do t = prod( t, t ) end
drawFractals( t )
end
function love.draw()
love.graphics.draw( canvas )
end
 

PARI/GP[edit]

Note
Works with: PARI/GP version 2.9.1 and above
File:VicsekFractalgp.png
Output VicsekFractalgp.png
File:SierpCarpetFractalgp.png
Output SierpCarpetFractalgp.png
File:SierpTriFractalgp.png
Output SierpTriFractalgp.png
 
\\ Build block matrix applying Kronecker product to the special matrix m
\\ (n times to itself). Then plot Kronecker fractal. 4/25/2016 aev
pkronfractal(m,n=2,clr)={
my(r=m);
for(i=1,n, r=matkronprod(r,m));
iPlotmat(r,clr);
}
\\Requireq tests:
{\\ Vicsek fractal: VicsekFractalgp.png
my(M=[0,1,0;1,1,1;0,1,0]); print(" *** Vicsek fractal, order 4:");
pkronfractal(M,4,6);
}
{\\ Sierpinski carpet fractal: SierpCarpetFractalgp.png
my(M=[1,1,1;1,0,1;1,1,1]); print(" *** Sierpinski carpet fractal, order 4:");
pkronfractal(M,4,5);
}
{\\ Sierpinski triangle fractal: SierpTriFractalgp.png
my(M=[1,1;0,1]); print(" *** Sierpinski triangle fractal, order 7:");
pkronfractal(M,7,6);
}
 
Output:
 *** Vicsek fractal, order 4:
 *** matrix(243x243) 3125 DOTS

 *** Sierpinski carpet fractal, order 4:
 *** matrix(243x243) 32768 DOTS 

 *** Sierpinski triangle fractal, order 7:
 *** matrix: 256x256, 6561 DOTS

Perl 6[edit]

Works with: Rakudo version 2017.03
sub kronecker-product ( @a, @b ) { (@a X @b).map: { (.[0].list X* .[1].list).Array } }
 
sub kronecker-fractal ( @pattern, $order = 4 ) {
my @kronecker = @pattern;
@kronecker = kronecker-product(@kronecker, @pattern) for ^$order;
@kronecker
}
 
use Image::PNG::Portable;
 
#Task requirements
my @vicsek = ( [0, 1, 0], [1, 1, 1], [0, 1, 0] );
my @carpet = ( [1, 1, 1], [1, 0, 1], [1, 1, 1] );
my @six = ( [0,1,1,1,0], [1,0,0,0,1], [1,0,0,0,0], [1,1,1,1,0], [1,0,0,0,1], [1,0,0,0,1], [0,1,1,1,0] );
 
for 'vicsek', @vicsek, 4,
'carpet', @carpet, 4,
'six', @six, 3
-> $name, @shape, $order {
my @img = kronecker-fractal( @shape, $order );
my $png = Image::PNG::Portable.new: :width(@img[0].elems), :height(@img.elems);
for ^@img[0] X ^@img -> ($x, $y) {
$png.set: $x, $y, |( @img[$y;$x] ?? <255 255 32> !! <16 16 16> );
}
$png.write: "kronecker-{$name}-perl6.png";
}

See Kronecker-Vicsek, Kronecker-Carpet and Kronecker-Six images.

R[edit]

Generate and plot 3 Kronecker product based fractals.
Note: Find plotmat() and plotv2() here on Helper Functions page.

Works with: R version 3.3.2 and above
File:VicsekFractalR.png
Output VicsekFractalR.png
File:SierpCarpetFR.png
Output SierpCarpetFR.png
File:PlusSignFR.png
Output PlusSignFR.png
 
## Generate and plot Kronecker product based fractals. aev 8/12/16
## gpKronFractal(m, n, pf, clr, ttl, dflg=0, psz=600):
## Where: m - initial matrix (filled with 0/1); n - order of the fractal;
## pf - plot file name (without extension); clr - color; ttl - plot title;
## dflg - writing dump file flag (0/1); psz - picture size.
gpKronFractal <- function(m, n, pf, clr, ttl, dflg=0, psz=600) {
cat(" *** START:", date(), "n=", n, "clr=", clr, "psz=", psz, "\n");
cat(" *** Plot file -", pf, "\n");
r <- m;
for(i in 1:n) {r = r%x%m};
plotmat(r, pf, clr, ttl, dflg, psz);
cat(" *** END:", date(), "\n");
}
 
## Required tests:
# 1. Vicsek Fractal
M <- matrix(c(0,1,0,1,1,1,0,1,0), ncol=3, nrow=3, byrow=TRUE);
gpKronFractal(M, 4, "VicsekFractalR","red", "Vicsek Fractal n=4")
# 2. Sierpinski carpet fractal
M <- matrix(c(1,1,1,1,0,1,1,1,1), ncol=3, nrow=3, byrow=TRUE);
gpKronFractal(M, 4, "SierpinskiCarpetFR", "maroon", "Sierpinski carpet fractal n=4")
 
# 3. Plus sign fractal
M <- matrix(c(1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1,1,
+0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1), ncol=7, nrow=7, byrow=TRUE);
gpKronFractal(M, 3, "PlusSignFR", "maroon", "Plus sign fractal, n=3")
 
# Also, try these 3. I bet you've never seen them before.
# 4. Wider Sierpinski carpet fractal (a.k.a. Sierpinski carpet mutant)
# Note: If your computer is not super fast it could take a lot of time.
# Use dump flag = 1, to save generated fractal.
#M <- matrix(c(1,1,1,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,1,1,1), ncol=5,
#+nrow=5, byrow=TRUE);
#gpKronFractal(M, 4, "SierpinskiCarpetFw", "brown", "Wider Sierpinski carpet fractal n=4", 1)
# 5. "H" fractal (Try all other letters in the alphabet...)
#M <- matrix(c(1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,
#+0,1,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1), ncol=7, nrow=7, byrow=TRUE);
#gpKronFractal(M, 3, "HFR", "maroon", "'H' fractal n=3", 1)
# 6. Chessboard fractal.
#M <- matrix(c(1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,
# 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1), ncol=8, nrow=8, byrow=TRUE);
#gpKronFractal(M, 2, "ChessBrdFractalR","black", "Chessboard Fractal, n=2")
 
Output:
> M <- matrix(c(0,1,0,1,1,1,0,1,0), ncol=3, nrow=3, byrow=TRUE);
> gpKronFractal(M, 4, "VicsekFractalR", "red", "Vicsek Fractal n=4")
 *** START: Mon Aug 29 16:14:14 2016 n= 4 clr= red 
 *** Plot file - VicsekFractalR 
 *** Matrix( 243 x 243 ) 3125  DOTS
 *** END: Mon Aug 29 16:14:14 2016 

> M <- matrix(c(1,1,1,1,0,1,1,1,1), ncol=3, nrow=3, byrow=TRUE);
> gpKronFractal(M, 4, "SierpinskiCarpetFR", "maroon", "Sierpinski carpet fractal n=4")
 *** START: Mon Aug 29 16:16:14 2016 n= 4 clr= maroon 
 *** Plot file - SierpinskiCarpetFR
 *** Matrix( 243 x 243 ) 32768  DOTS
 *** END: Mon Aug 29 16:16:32 2016 

> M <- matrix(c(1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,0,0,0,0,0,1,1,1,1,
+0,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1), ncol=7, nrow=7, byrow=TRUE);
> gpKronFractal(M, 3, "PlusSignFR", "maroon", "Plus sign fractal, n=3")
 *** START: Thu Apr 06 21:45:33 2017 n= 3 clr= maroon psz= 600 
 *** Plot file - PlusSignFR 
 *** Matrix( 2401 x 2401 ) 2560000 DOTS
 *** END: Fri Apr 07 09:31:07 2017 

REXX[edit]

/*REXX program calculates the   Kronecker product   of   two arbitrary size   matrices. */
parse arg pGlyph . /*obtain optional argument from the CL.*/
if pGlyph=='' | pGlyph=="," then pGlyph='█' /*Not specified? Then use the default.*/
if length(pGlyph)==2 then pGlyph=x2c(pGlyph) /*Plot glyph is 2 chars? Hexadecimal.*/
if length(pGlyph)==3 then pGlyph=d2c(pGlyph) /* " " " 3 " Decimal. */
aMat= 3x3 0 1 0 1 1 1 0 1 0 /*define A matrix size and elements.*/
bMat= 3x3 1 1 1 1 0 1 1 1 1 /* " B " " " " */
call makeMat 'A', aMat /*construct A matrix from elements.*/
call makeMat 'B', bMat /* " B " " " */
call KronMat 'Kronecker product' /*calculate the Kronecker produect. */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
KronMat: parse arg what; #=0; parse var @.a.shape aRows aCols
parse var @.b.shape bRows bCols
do rA=1 for aRows
do rB=1 for bRows; #=#+1; ##=0; _=
do cA=1 for aCols; x=@.a.rA.cA
do cB=1 for bCols; y=@.b.rB.cB; ##=##+1; xy=x*y; _=_ xy
@.what.#.##=xy
end /*cB*/
end /*cA*/
end /*rB*/
end /*rA*/
call showMat what, aRows*bRows || 'X' || aRows*bCols; return
/*──────────────────────────────────────────────────────────────────────────────────────*/
makeMat: parse arg what, size elements; arg , row 'X' col .; @.what.shape= row col
#=0; do r=1 for row /* [↓] bump item#; get item; max width*/
do c=1 for col; #=#+1; @.what.r.c=word(elements, #)
end /*c*/ /* [↑] define an element of WHAT matrix*/
end /*r*/
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
showMat: parse arg what, size .; parse var size row 'X' col /*obtain mat name, sz*/
parse value scrsize() with sd sw .; sdu=sd-3; swu=sw-1 /*obtain screen size.*/
rows=0 /*number rows shown. */
do forever /*display until full.*/
do r=1 for row; $= /*build row by row. */
do c=1 for col; $=$ || @.what.r.c /* " col " col. */
end /*c*/
$=translate($, pGlyph, 10) /*change──►plot glyph*/
do until length($)>=swu; $=$ || $ /*compound 'til full.*/
end /*until*/
say strip(left($, swu), 'T') /*display line──►term*/
rows=rows+1 /*bump the # of rows.*/
if rows>=sdu then return /*Screen full? Done.*/
end /*r*/
end /*forever*/
output   when using the default input:


(Shown at quarter size.)

   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
   █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █      █ █
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
█ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
   ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███      ███

Sidef[edit]

Translation of: Perl 6
func kronecker_product (a, b) { a ~X b -> map { _[0] ~X* _[1] } }
 
func kronecker_fractal(pattern, order=4) {
var kronecker = pattern
{ kronecker = kronecker_product(kronecker, pattern) } * order
return kronecker
}
 
var vicsek = [[0,1,0], [1,1,1], [0,1,0]]
var carpet = [[1,1,1], [1,0,1], [1,1,1]]
var six = [[0,1,1,1,0], [1,0,0,0,1], [1,0,0,0,0],
[1,1,1,1,0], [1,0,0,0,1], [1,0,0,0,1], [0,1,1,1,0]]
 
require("Imager")
 
for name,shape,order in [
[:vicsek, vicsek, 4],
[:carpet, carpet, 4],
[:six, six, 3],
] {
var pat = kronecker_fractal(shape, order)
var img = %O<Imager>.new(xsize => pat[0].len, ysize => pat.len)
for x,y in (^pat[0].len ~X ^pat.len) {
img.setpixel(x => x, y => y, color => (pat[y][x] ? <255 255 32> : <16 16 16>))
}
img.write(file => "kronecker-#{name}-sidef.png")
}

zkl[edit]

Uses Image Magick and the PPM class from http://rosettacode.org/wiki/Bitmap/Bresenham%27s_line_algorithm#zkl

var [const] GSL=Import.lib("zklGSL");    // libGSL (GNU Scientific Library)
fcn kronecker(A,B){ //--> new Matrix
m,n, p,q := A.rows,A.cols, B.rows,B.cols;
r:=GSL.Matrix(m*p, n*q);
foreach i,j,k,l in (m,n,p,q){ r[p*i + k, q*j + l]=A[i,j]*B[k,l] }
r
}
 
fcn kfractal(M,n,fname){
R:=M;
do(n){ R=kronecker(R,M) }
r,c,img := R.rows, R.cols, PPM(r,c,0xFFFFFF); // white canvas
foreach i,j in (r,c){ if(R[i,j]) img[i,j]=0x00FF00 } // green dots
println("%s: %dx%d with %,d points".fmt(fname,R.rows,R.cols,
R.pump(0,Ref(0).inc,Void.Filter).value)); // count 1s in fractal matrix
img.writeJPGFile(fname);
}
var [const] A=GSL.Matrix(3,3).set(0,1,0, 1,1,1, 0,1,0),
B=GSL.Matrix(3,3).set(1,1,1, 1,0,1, 1,1,1);
kfractal(A,4,"vicsek_k.jpg");
kfractal(B,4,"sierpinskiCarpet_k.jpg");
Output:
vicsek_k.jpg: 243x243 with 3,125 points
sierpinskiCarpet_k.jpg: 243x243 with 32,768 points

Images at Vicsek fractal and Sierpinski Carpet fractal.