# Studio/FractalsVisualizationJ

-- Chapter 1 Introduction -----------------------------------

((1) 1 of 21) Introduction ------------------------------- This lab is designed to provide a hands-on introduction to the visualization of mathematical objects, algorithms and data. This includes the plotting of functions in two and three dimensions, the creation of fractals using a wide variety of methods and the manipulation of data and images in general.

The lab is based on the first 2 chapters of "Fractals, Visualization & J" by Cliff Reiter.

The lab makes essential use of the standard graph utilities. If necessary, first take the lab "Graph Utilities".

((1) 2 of 21) Introduction (ctd) ------------------------- We require the graph, numeric and trig libraries, which can be loaded as follows:

load 'graph numeric trig'

((1) 3 of 21) Terminology -------------------------------- Some terminology:

"object graphics" are drawn with the objects supported by the Windows graphic interface (GDI), for example, lines and polygons. In J, these can be drawn directly using the graph package.

"raster graphics" are drawn by plotting suitable pixels. In J, these are drawn as bitmaps.

This chapter has examples of both types: drawing a polygon using object graphics, and a Sierpinksi triangle using raster graphics.

((1) 4 of 21) Terminology (ctd) -------------------------- The lab will show drawings in one or more windows. You can rearrange and resize these windows as required.

The windows can be left open as you step through the lab. However, you can also close them if you wish - they will be re-created when they are next used.

((1) 5 of 21) Terminology (ctd) -------------------------- You are encouraged to experiment as you go through the course.

You can modify and re-enter examples by moving the cursor up to a line in the session manager, and pressing enter.

For example, the next two sections draw a pentagon. Try modifying the example to draw a hexagon.

((1) 6 of 21) Experiment: Plotting Polygons -------------- We start with an example of object graphics: a drawing of a 5-sided regular polygon, i.e. a pentagon. First generate 5 points equally spaced on a unit circle, and draw a polygon from them.

The calculations are shown below. The next section draws the polygon.

NB. divide 2 pi into five intervals: 2p1*(i.5)%5 0 1.25664 2.51327 3.76991 5.02655 NB. generate the points as cosine-sine pairs: +. r. 2p1*(i.5)%5 1 0 0.309017 0.951057 _0.809017 0.587785 _0.809017 _0.587785 0.309017 _0.951057

((1) 7 of 21) Experiment: Plotting Polygons (ctd) -------- Draw the polygon.

The commands used open a graph window, draw the polygon, then show the window.

Note that the right argument to gdpolyon should be a list of points. A matrix would be treated as a separate polygon drawing for each row.

Now try drawing a blue hexagon (6 sides) before continuing the lab.

gdopen '' RED gdpolygon ,+. r. 2p1*(i.5)%5 gdshow''

((1) 8 of 21) Experiment: Plotting Polygons (ctd) -------- The same technique can be used for regular polygons of any number of sides.

The utility int01 can be used to generate the intervals. This produces an extra value at the end, but this does not affect the drawing.

Try varying the 2p1 multiplier to produce different shapes.

((i.5)%5) ; int01 5 +-----------------+-------------------+ |0 0.2 0.4 0.6 0.8|0 0.2 0.4 0.6 0.8 1| +-----------------+-------------------+ gdopen '' BLUE gdpolygon ,+. r. 6p1 * int01 11 gdshow''

((1) 9 of 21) Simplify Code ------------------------------ We can simplify the code a little here.

First, the utility "polygon" can be used to generate the required values for a regular polygon. The optional left argument is a scale factor on the multiplier 2p1. The result of polygon is cleaned, i.e. values near 0 are set to 0.

For example:

(+. r. 6p1 * int01 11) ; 3 polygon 11 +-------------------+-------------------+ | 1 0| 1 0| |_0.142315 0.989821|_0.142315 0.989821| |_0.959493 _0.281733|_0.959493 _0.281733| | 0.415415 _0.909632| 0.415415 _0.909632| | 0.841254 0.540641| 0.841254 0.540641| |_0.654861 0.75575|_0.654861 0.75575| |_0.654861 _0.75575|_0.654861 _0.75575| | 0.841254 _0.540641| 0.841254 _0.540641| | 0.415415 0.909632| 0.415415 0.909632| |_0.959493 0.281733|_0.959493 0.281733| |_0.142315 _0.989821|_0.142315 _0.989821| | 1 0| 1 0| +-------------------+-------------------+

((1) 10 of 21) Simplify Code (ctd) ----------------------- Next, the sequence:

gdopen'' gdpolygon data gdshow''

can be written in a single line, as:

gdpolygon gddraw data

Here, gddraw is an adverb that wraps its left argument between gdshow and gdopen.

((1) 11 of 21) Simplify Code (ctd) ----------------------- For example, the line of code run below is equivalent to:

gdopen'' TEAL gdpolygon ,7 polygon 15 gdshow''

TEAL gdpolygon gddraw ,7 polygon 15

((1) 12 of 21) Simplify Code (ctd) -----------------------
This lab will, for the most part, employ the short form using
gddraw. If you have trouble following the code, you should
re-enter it using the steps `gdopen`, `gdpolygon...` and `gdshow''`

((1) 13 of 21) Graph Windows ----------------------------- The windows used so far are named "graph".

This lab sometimes generates windows named "lab", as in the next section. The idea is that you can experiment with the "graph" window while the "lab" window remains open.

((1) 14 of 21) Graph Windows (ctd) ----------------------- See if you can reproduce the "lab" figure.

((1) 15 of 21) Sierpinksi Triangle ----------------------- Now we look at an example of raster graphics.

A Sierpinski triangle can be generated by repeated copying.

Given a matrix m1, try to find a J expression that will create another matrix, m2, of the form:

m1 m1 m1 0

For example, if m1 is:

1 1 1 0

then m2 should be:

1 1 1 1 1 0 1 0 1 1 0 0 1 0 0 0

NB. define m1: [m1=: 1 1 ,: 1 0 1 1 1 0

((1) 16 of 21) Sierpinksi Triangle (ctd) ----------------- A simple verb to do this is:

f=: ,~,.~ f m1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 0 0 f ,1 NB. generates m1 1 1 1 0 f f ,1 1 1 1 1 1 0 1 0 1 1 0 0 1 0 0 0 f ^:3 ,1 1 1 1 1 1 1 1 1 1 0 1 0 1 0 1 0 1 1 0 0 1 1 0 0 1 0 0 0 1 0 0 0 1 1 1 1 0 0 0 0 1 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0

((1) 17 of 21) Sierpinksi Triangle (ctd) ----------------- Try entering:

f ^:6 ,1

You can browse this matrix using:

wdview f ^:6 ,1

((1) 18 of 21) Sierpinksi Triangle (ctd) ----------------- The viewmat utility can be used to display the matrix.

((1) 19 of 21) Sierpinksi Triangle (ctd) -----------------

viewmat f ^: 4 ,1

((1) 20 of 21) Sierpinksi Triangle (ctd) ----------------- Exeriment with different powers of f, for example, try:

viewmat f ^: 6 ,1

Each iteration increases the number of points 4 fold, so it is not advisable to try much higher powers.

A left argument of a color matrix can be used to set colors. Try:

(TEAL ,: RED) viewmat f ^: 6 ,1

((1) 21 of 21) Sierpinski Carpet ------------------------- The same principle can be used to construct the Sierpinski carpet.

Can you duplicate the "lab" example?

-- Chapter 2 Fractals and Transformations -------------------

((2) 1 of 50) Introduction ------------------------------- In this chapter we look at organizing and applying the mathematics required for creating transformations of the plane: rotations, rescaling and translations. This is done in a uniform way by using homogeneous coordinates.

The work on transformations prepares the way for a deeper look at fractals. In particular, iterated function systems and some recursive refinement methods are described.

((2) 2 of 50) Introduction (ctd) ------------------------- Note that the standard graphics box is a square from _1 _1 to 1 1. The objects defined in the lab fit in this box, but might not do so after being transformed.

If an object cannot be seen when you display it, check its coordinates. If necessary, scale down the object to fit into the standard box.

((2) 3 of 50) Plotting Functions and Parametric Curves --- Now lets experiment with plotting functions.

Define x to be 1000 points in the range from _1 to 1, then draw x against sin pi times x.

steps _1 1 10 _1 _0.8 _0.6 _0.4 _0.2 0 0.2 0.4 0.6 0.8 1 x=: steps _1 1 1000 y=: sin o. x gdlines gddraw ,x ,. y

((2) 4 of 50) Plotting Functions and Parametric Curves (ctd) In the previous example, we specified x, and then defined y as a function of x.

In a parametric plot, both x and y are functions of some variable, typically denoted t.

In the example, a factor of 0.9 shrinks the plot to fit comfortably in the graph box:

t=: steps 0 2p1 1000 x=: cos t y=: sin t gdlines gddraw ,0.9 * x,.y

((2) 5 of 50) Plotting Functions and Parametric Curves (ctd) Here is an equivalent expression that makes it easier to think in terms of the two functions being graphed:

gdlines gddraw ,0.9 * +. r. t

((2) 6 of 50) Plotting Functions and Parametric Curves (ctd) Modify these functions for some interesting experiments.

For example, try:

gdlines gddraw ,0.9 * (cos ,. sin*cos) t gdlines gddraw ,0.9 * (cos@(3&*) ,. sin) t gdlines gddraw ,0.9 * (cos@(3&*) ,. sin@(2&*)) t

((2) 7 of 50) Plotting Functions and Parametric Curves (ctd) Can you reproduce the "lab" example?

((2) 8 of 50) Plotting Functions and Parametric Curves (ctd) Note that all plots are parametric.

For example, here is the first plot written in parametric style:

t=: steps _1 1 1000 gdlines gddraw ,(] ,. sin@o.) t

((2) 9 of 50) Plotting Functions and Parametric Curves (ctd) swap the x and y functions:

gdlines gddraw ,(sin@o. ,. ]) t

((2) 10 of 50) The Koch Snowflake ------------------------ The Koch curve and snowflake are curves that are described by iterative refinement. When this refinement is applied to an initial triangle, the Koch snowflake results.

The basic step in the iterative process is to take an edge and replace it with four edges introducing a bulge. If the given edge is trisected, then the two end thirds are retained and the center third is replaced by the other two edges of an equilateral triangle placed on the center third.

((2) 11 of 50) The Koch Snowflake (ctd) ------------------ As a specific example of refining an edge consider an edge from 0 0 to 1 0 which can be specified by the rows of the matrix, each row specifying one vertex (endpoint):

0 0 1 0

((2) 12 of 50) The Koch Snowflake (ctd) ------------------ Applying the basic step to this edge would result in the following vertex sequence (polygon) where y is -%:%12 :

0 0 1r3 0 1r2 y 2r3 0 1 0

((2) 13 of 50) The Koch Snowflake (ctd) ------------------ In order to implement this subdivision we define functions that calculate the midpoint and the points which divide the segment into thirds.

tri1=: 2r3&*@[ + 1r3&*@] NB. one third point tri2=: 1r3&*@[ + 2r3&*@] NB. two thirds point mid=: -:@+ NB. midpoint 0 0 tri1 1 0 1r3 0 0 0 tri2 1 0 2r3 0 0 0 mid 1 0 0.5 0 |. 5 6 7 8 NB. reverse items 8 7 6 5 nor=: _1 1&*@|. NB. left normal vector nor 1 2 _2 1 bulge=: mid + (%:%12)&*@nor@:- NB. bulge point 0 0 bulge 1 0 0.5 _0.288675

((2) 14 of 50) The Koch Snowflake (ctd) ------------------ Note that bulge uses the at composition @:, so that nor@:- finds the normal to the vector difference, not the normal to each element in the difference.

Compare:

nor@- 1 2 1 _1 2 _2 nor@:- 1 2 2 _1

((2) 15 of 50) The Koch Snowflake (ctd) ------------------ Thus, bulge computes the midpoint with a displacement in the opposite of the left normal direction. Below, segdiv divides up the given segment into pieces.

Note that the last point is not included in the result since it will be included as the first point in the next segment to be refined.

segdiv=: [ , tri1 , bulge ,: tri2 0 0 segdiv 1 0 0 0 0.333333 0 0.5 _0.288675 0.666667 0

((2) 16 of 50) The Koch Snowflake (ctd) ------------------ The function refine applies the division to neighboring pairs of vertices.

i. 4 3 0 1 2 3 4 5 6 7 8 9 10 11 1|.i. 4 3 NB. rotate items by one position cyclically 3 4 5 6 7 8 9 10 11 0 1 2 refine=: ,/@(] segdiv"1 (1&|.))

((2) 17 of 50) The Koch Snowflake (ctd) ------------------ Generate a snowflake with a single iteration of refine.

In this lab, snow is usually red.

[p=: |:2 1 o./ 2r3p1*i.3 NB. make a triangle 1 0 _0.5 0.866025 _0.5 _0.866025 RED gdpolygon gddraw ,refine ^:1 p

((2) 18 of 50) The Koch Snowflake (ctd) ------------------ Generate a snowflake with four iterations of refine.

RED gdpolygon gddraw ,refine ^:4 p

((2) 19 of 50) The Koch Snowflake (ctd) ------------------ An experiment with superimposing the snowflakes.

Note that arguments to gdpolygon can be boxed lists.

(BLUE;RED) gdpolygon gddraw (,refine ^:4 p);,refine ^:1 p

((2) 20 of 50) The Koch Snowflake (ctd) ------------------ Can you reproduce the lab figure?

((2) 21 of 50) Transformations and Homogeneous Coordinates The dot product of two vectors is computed by taking the sum of the pairwise products of the elements of two given vectors. The standard matrix product generalizes this so that the result is the dot product of each row of the left argument with each column of the right argument.

In J, the matrix and dot products are both denoted by the inner product:

+/ . *

1 _1 2 +/ . * 0 2 4 NB. dot product 6 [a=: i.3 2 0 1 2 3 4 5 [b=: 0 1,:1 2 0 1 1 2 a +/ . * b NB. matrix product 1 2 3 8 5 14

((2) 22 of 50) Transformations --------------------------- Matrices can be used to represent transformations of the plane.

Suppose p is a vector giving the x-y coordinates of a point in the plane. If we want to expand or contract in the x-direction by a factor of r and in the y-direction by a factor of s, then multiplying p on the right by a matrix of the following form will effect the transformation.

r 0 0 s

For example, the matrix a rescales the x-direction by a factor of 3.

[a=: 2 2$3 0 0 1 3 0 0 1 [p=: 10 10 10 10 p +/ . * a 30 10

((2) 23 of 50) Rotations --------------------------------- If we want to rotate a point p through an angle of t counterclockwise about the origin, we can multiply by a matrix of the following form.

cos(t) sin(t) -sin(t) cos(t)

Let nor be defined as before, then we can construct a rotation matrix a as follows.

nor=: _1 1&*@|. [a=: (,: nor) 2 1 o. 1r6p1 NB. rotate by 1r6p1 0.866025 0.5 _0.5 0.866025 1 0 +/ . * a 0.866025 0.5 p=: 10 10 p +/ . * a 3.66025 13.6603

((2) 24 of 50) Translations ------------------------------ Lastly, if we want to translate, we can just add.

Thus, to move a point, p, 1 unit to the right and 2 units upward, add:

p + 1 2

((2) 25 of 50) Translations (ctd) ------------------------ One often wants to think about transformations in the plane as a sequence of rotations, rescalings and translations. It is somewhat awkward to do this using the above ideas since the compositions will be a matrix product plus some translation vector.

In order to help organize the desired compositions, we use a slightly different coordinate system that allows all three types of transformations to be implemented with matrix multiplication. These are called homogeneous coordinates.

((2) 26 of 50) Homogeneous Coordinates ------------------- Basically, we simply attach a trailing 1 to each x-y pair. More precisely, we consider two triples to represent the homogeneous coordinates of the same point in the plane if they are different by a nonzero scalar multiple, so 3 2 1 and 6 4 2 denote the same point in homogeneous coordinates.

We will always scale homogeneous coordinates so there is a trailing 1.

Now to rescale by r and s, rotate by t, or translate by u,v we multiply p,1 by a matrix of one of the following forms.

rescaling rotation translation r 0 0 cos(t) sin(t) 0 1 0 0 0 s 0 -sin(t) cos(t) 0 0 1 0 0 0 1 0 0 1 u v 1

((2) 27 of 50) Homogeneous Coordinates (ctd) ------------- For example, if transformation matrices a1, a2, and a3 are defined as below, then the result of applying them to the point 1 1 after it is converted to homogeneous coordinates is shown.

NB. matrix a1 rescales x by 3 [a1=: 3 0 0, 0 1 0,: 0 0 1 3 0 0 0 1 0 0 0 1 10 10 1 +/ . * a1 30 10 1 NB. matrix a2 rotates by 45 [a2=: ((-:%:2) * 1 1 0,:_1 1 0),0 0 1 0.707107 0.707107 0 _0.707107 0.707107 0 0 0 1 10 10 1 +/ . * a2 0 14.1421 1 NB. matrix a3 translates by 1 2 [a3=: 1 0 0, 0 1 0,: 1 2 1 1 0 0 0 1 0 1 2 1 10 10 1 +/ . * a3 11 12 1

((2) 28 of 50) Experiment: Some Transformations ---------- Begin by defining a matrix p whose rows give the homogeneous coordinates of an L-shaped polygon.

[p=: (0.25 * 6 2$0 0 2 0 2 1 1 1 1 3 0 3) ,.1 0 0 1 0.5 0 1 0.5 0.25 1 0.25 0.25 1 0.25 0.75 1 0 0.75 1

((2) 29 of 50) Experiment: Some Transformations (ctd) ---- Display the L-shape

RED gdpolygon gddraw ,}:"1 p

((2) 30 of 50) Experiment: Some Transformations (ctd) ---- Now let a1 be a matrix and t1 the transformation associated with matrix multiplication by a1 on the right.

The next draws t1 p.

How are the polygons p and t1 p related?

[a1=: 0.5 0 0,0 0.5 0,:0 0 1 0.5 0 0 0 0.5 0 0 0 1 t1=: +/ .* & a1

((2) 31 of 50) Experiment: Some Transformations (ctd) ---- Draw p and t1 p.

(RED;BLUE) gdpolygon gddraw (,}:"1 p);(,}:"1 t1 p)

((2) 32 of 50) Experiment: Some Transformations (ctd) ---- Experiment with the following transformation matrices.

[a2=: _1 0 0, 0 _1 0,: 0 0 1 _1 0 0 0 _1 0 0 0 1 [a3=: 2 0 0, 0 1 0,: 0 0 1 2 0 0 0 1 0 0 0 1 [a4=: 0.5 0 0, 0 _0.5 0,: 0 0 1 0.5 0 0 0 _0.5 0 0 0 1 [a5=: 1 0 0, 0 1 0,: _1 _1 1 1 0 0 0 1 0 _1 _1 1 t2=: +/ .* & a2 t3=: +/ .* & a3 t4=: +/ .* & a4 t5=: +/ .* & a5

((2) 33 of 50) Experiment: Some Transformations (ctd) ---- For example, try:

(RED;BLUE) gdpolygon gddraw (,}:"1 p);(,}:"1 t2 p)

((2) 34 of 50) Transformation Exercises ------------------ Let t6 be the transformation resulting from a4 +/ . * a5.

Display t6 p and compare the result of t4@t5 p with t6 p.

How do these compare to the result of the transformation, t7, associated with a5 +/ . * a4?

t6=: +/ . * & (a4 +/ . * a5) t7=: +/ . * & (a5 +/ . * a4)

((2) 35 of 50) Transformation Exercises (ctd) ------------ Define a function rot such that rot y gives the rotation matrix (in homogeneous coordinates) of a rotation through an angle y.

Create a transformation t8 that rotates by an angle of p/3. Apply it to p and view the result.

Compare t8@t5 and t5@t8.

((2) 36 of 50) Transformation Exercises (ctd) ------------ Next consider transformations associated with the identity matrix and inverse matrices.

Plot and view the results of those transformations on p.

]a9=. =i.3 NB. 3 by 3 identity matrix 1 0 0 0 1 0 0 0 1 ]a10=. %. a3 NB. matrix inverse to a3 0.5 0 0 0 1 0 0 0 1 ]a11=. %. a5 NB. another inverse 1 0 0 0 1 0 1 1 1 ]a12=. %. a8 NB. another inverse 0.5 _0.866025 0 0.866025 0.5 0 0 0 1

((2) 37 of 50) Experiment: Some Collages of Transformations Define p to be a polygon in homogeneous coordinates giving the unit square with one vertex at the origin.

Define three transformations, t0, t1, t2 as follows:

[p=: (#:0 1 3 2),.1 0 0 1 0 1 1 1 1 1 1 0 1 [a0=: 0.5 0 0, 0 0.5 0,: 0 0 1 0.5 0 0 0 0.5 0 0 0 1 [a1=: 0.5 0 0, 0 0.5 0,: 0.5 0 1 0.5 0 0 0 0.5 0 0.5 0 1 [a2=: 0.5 0 0, 0 0.5 0,: 0 0.5 1 0.5 0 0 0 0.5 0 0 0.5 1 t0=: +/ . * & a0 t1=: +/ . * & a1 t2=: +/ . * & a2

((2) 38 of 50) Experiment: Some Collages of Transformations (ctd) We want to create a collage of the transformations on the polygon. That is, we want the list of the three polygons that result from applying t0, t1 and t2 to p.

This is easy to implement using gerunds and gerund evaluate as below.

collage=: t0`t1`t2`:0 collage p 0 0 1 0 0.5 1 0.5 0.5 1 0.5 0 1 0.5 0 1 0.5 0.5 1 1 0.5 1 1 0 1 0 0.5 1 0 1 1 0.5 1 1 0.5 0.5 1

((2) 39 of 50) Experiment: Some Collages of Transformations (ctd) Experiment with powers of collage, for example:

collage ^: 2 p

Now draw each matrix of the result.

((2) 40 of 50) Experiment: Some Collages of Transformations (ctd) For example:

RED gdpolygon01 gddraw ,"2 }:"1 collage ^: 6 p

((2) 41 of 50) Experiment: Some Collages of Transformations (ctd) Repeat the experiment with the same transformations but use a five-pointed star (or some other polygon) as the starting polygon.

How does this affect the long term pattern?

((2) 42 of 50) Experiment: Iteration of Random Transformations It turns out that object graphics cannot handle many thousands of objects. Thus when creating an image with many thousands of pixels, a pixel at a time, we do well to avoid object based graphics. Since arrays are easy to create in J we will create a large array giving a virtual screen. This can be viewed as a bitmap.

((2) 43 of 50) Experiment: Iteration of Random Transformations (ctd) Again define three transformations, t0, t1, t2 corresponding to the matrices you used in Section 2.9 to create a finite version of the Sierpinski triangle.

Now ?@3: is a function that, when applied to anything, randomly picks a number from 0 1 2. The function rt, given below, randomly applies one of the transformations to the input data and rt^:(i.5) applies a random transformation to the given input 4 times and catenates the results to the matrix.

rt=: t0`t1`t2@.(?@3:) rt 0.9 0.9 1 0.45 0.95 1 rt^:(i.5) 0.9 0.9 1 0.9 0.9 1 0.95 0.45 1 0.975 0.225 1 0.9875 0.1125 1 0.49375 0.55625 1

((2) 44 of 50) Experiment: Iteration of Random Transformations (ctd) To view the result of rt in a bitmap, scale the result to the size of the bitmap, round to nearest integer and use as indices to insert 1 into a matrix of zeroes. Here we use a bitmap of size 500x500.

For example:

a=: }:"1 rt^:(i.125) 0.9 0.9 1 viewmat |.|: 1 (;/roundint 499 * a) } 500 500$0

((2) 45 of 50) Experiment: Iteration of Random Transformations (ctd) The last expression to view a set of indices will be used repeatedly, so we define a verb viewndx for it:

viewndx=: 3 : 'viewmat |.|: 1 (;/roundint 499 * y.) } 500 500$0' viewndx a

((2) 46 of 50) Experiment: Iteration of Random Transformations (ctd) No pattern is discernable with only 125 values.

However, crank this up and the fractal starts to appear.

Repeat with 10000 values.

viewndx }:"1 rt^:(i.1000) 0.9 0.9 1

((2) 47 of 50) Experiment: Iteration of Random Transformations (ctd) Next try a different set of transformations.

Modify the above (including rt) to handle the four transformations associated with the following matrices.

[a3=: 0 0 0, 0 0.16 0,: 0.25 0 1 0 0 0 0 0.16 0 0.25 0 1 [a4=: 0.85 _0.04 0, 0.04 0.85 0,: 0.0375 0.17 1 0.85 _0.04 0 0.04 0.85 0 0.0375 0.17 1 [a5=: 0.2 0.23 0, _0.26 0.22 0,: 0.2 0.1025 1 0.2 0.23 0 _0.26 0.22 0 0.2 0.1025 1 [a6=: _0.15 0.26 0, 0.28 0.24 0,: 0.2875 _0.021 1 _0.15 0.26 0 0.28 0.24 0 0.2875 _0.021 1 t3=: +/ . * & a3 t4=: +/ . * & a4 t5=: +/ . * & a5 t6=: +/ . * & a6 rt=: t3`t4`t5`t6 @.(?@4:)

((2) 48 of 50) Experiment: Iteration of Random Transformations (ctd)

viewndx }:"1 rt^:(i.20000) 0.5 0.5 1

((2) 49 of 50) Experiment: Iteration of Random Transformations (ctd) Notice that the image looks like a fern, but the tip is very faint.

Modify rt so that it uses the same transformations, but the transformation associated with a4 is repeated 6 times (so a random number up to 9 is required). You should get a much better image.

((2) 50 of 50) Experiment: Iteration of Random Transformations (ctd) For example:

rt=: t3`t4`t5`t6 @.(?@9: { 0 1 1 1 1 1 1 2 3"_) viewndx }:"1 rt^:(i.20000) 0.5 0.5 1