Code Along – Maps part 2

gray kangaroo

A code-along is a story about coding in which you are encouraged to “code up” all the examples in the story. In a code-along you shouldnot cut-and-paste.

In this code-along, we will explore how to use the higher-function map to translate an integer list into a variety of vertex lists. We then show how these vertex lists can be concatenated and how map can again be used to connect the vertices in the resulting list to a central vertex.

The Bricklayer program in this example creates the graph shown below. It contains 16*4 + 1 = 65 vertices and 16*4 = 64 edges. In this graph, 1 central vertex c is connected via blue edges to 64 peripheral vertices, p0, …, p63.

map-2-example_01-hi-res

In this program, the central vertex is statically defined (line 10) in terms of the variable half. The peripheral vertices are created dynmically (i.e., during runtime) in the following manner. First, a listvs is statically defined (line 12) consisting of consecutive integers in the range 0…15. Then 4 user-defined functions are declared which translate integers into 2D coordinates. In a manner similar to that discussed in the previous code-along, the coordinates produced by these functions make use of variables. In this case, the variables delta and max are used.

The following things about how vertex lists are created are noteworthy.

  1. When passed to the higher-order function map (lines 14-17), each function creates list of 16 vertices.
  2. When seen as a whole, the four function calls to map create 64 vertices which are evenly distributed and fall on the 4 sides of a square-shaped region in the virtual space.
  3. The vertex lists created are disjoint (i.e., they have no vertices in common).
  4. Vertices are created that lie exactly on the 4 corners of the virtual square.
  5. Each of the four lists created corresponds to one side of a virtual square.
  6. Each of the four lists created contains one corner vertex.
  7. Each of the four lists created contains one vertex which lies on the midpoint of a side.

The user-defined function multiconnect is used to connect the peripheral vertices to the central vertex. The behavior of this function is the same here as it was in the previous code-along. In the call, the third argument to multiconnect (line 26) is a list that consists of the the concatenation of the 4 lists of peripheral vertices.

open Level_3;

val delta      = 8;
val dimensions = 16*delta+1;
val max        = dimensions - 1;
val half       = dimensions div 2;

fun graph () =
    let    
        val c = (half,half);
        
        val vs = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
        
        fun leftSideFn   v = (0  , v    *delta);
        fun rightSideFn  v = (max, (v+1)*delta);
                                                 
        fun bottomSideFn v = ((v+1)*delta, 0  );
        fun topSideFn    v = ( v   *delta, max);
        
        val left   = map leftSideFn   vs;
        val right  = map rightSideFn  vs;
        val bottom = map bottomSideFn vs;
        val top    = map topSideFn    vs;
        
        fun multiconnect b v vs =
            let
                fun connect v1 v2 = lineXZ v1 v2 b;                               
            in
                map (connect v) vs
            end; 


        val vertices = left @ right @ bottom @ top;
    in
        multiconnect BLUE c vertices    
    end;

(* ==================================================== *)  
build2D(dimensions,dimensions);

graph ();
  
show2D "Graph";

 

The Bricklayer program in this example creates the graph-like artifact shown below.

map-2-example_02-hi-res

The algorithm used to create this artifact is similar to that used in the previous example. The only difference is that one additional function call (line 27) is added that overwrites the graph with a ring of empty bricks. It is this ring that produces the effect shown.

open Level_3;

val delta      = 8;
val dimensions = 16*delta+1;
val max        = dimensions - 1;
val half       = dimensions div 2;

fun graph () =
    let      
        val vs = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
        
        fun leftSideFn  v = (0  , v*8);
        fun rightSideFn v = (max, v*8);

        fun bottomSideFn  v = (v*8, 0  );
        fun topSideFn     v = (v*8, max);
        
        val left   = map leftSideFn   vs;
        val right  = map rightSideFn  vs;
        val bottom = map bottomSideFn vs;
        val top    = map topSideFn    vs;
        
        val c = (half,half);
        
        fun multiconnect b v vs =
            let
                fun connect v1 v2 = lineXZ v1 v2 b;                               
            in
                map (connect v) vs
            end; 


        val vertices = left @ right @ bottom @ top;
    in
        multiconnect BLUE c vertices;
        ringXZ 64 20 EMPTY c          
    end;

(* ==================================================== *)    
build2D(dimensions,dimensions);

graph ();
  
show2D "Graph";