Arrays and loops

Let’s create an archive of all messages a node arrived. Therefor we’d like to store the messages in a list.

Arrays and lists

NetSimLan knows two kinds of arrays respectively lists. One are the array lists declared as type [] varname;, the others are linked lists declared as type <> varname;. Beside the declaration the syntax to interact with them is identical and they offer the same set of operations.

Let’s get started. Add a list or array of type string named messages to the attributes. After the message output add the message to the list:

messages[length(messages)] = text;

When you run the program, you’ll find all messages directed to a note in it’s message list.

There’s a shortcut for adding an element to a list’s end. Replace the assignment by the following line and rerun the program:

messages >> text;

We can also access or delete elements. Let’s say, we need to print and delete the first and last element or flush the message list. That may looks as follows:

printanddeletefirstandlast(){
    /* print first and last */
    print (messages[0]);
    print (messages[length(messages)-1]);
    /* delete first element */
    messages <[0]<;
    /* delete last element */
    messages <<;
}
flushmessages(){
    /* make message list empty */
    messages <<<<;
}

Inserting an element e on a arbitrary position i (not replacing the existing element but shifting it) may looks as follows:

messages >[i]> e;

Hint: You can use a (linked) list as stack or queue by adding an element to the end and read/delete the last resp. the first element.

All ways of assigning an element to an array position i mean: If the length of the array is less then i, it will be filled up with the default value of the array’s data type such that the array is long enough to contain the new element. If you read from an array position above the array’s length, you’ll read the default value of the array’s data type.

You can use multidimensional arrays and mix array lists and linked lists. Arrays with two or more dimensions can only be accessed by the v[i][j] syntax. Special operations like v»e are only possible for one dimensional arrays.

Loops

You can use three different kinds of loops: the while, the for and the foreach loop. As in other languages, while loops are as powerful as for loops and the other way around. On the other hand foreach loops are limited to iterate over a complete one dimensional array, but for that use they are more efficient.

However, let’s build a function to print all messages in our list. Let’s print the hole list three times, each time using another loop type. The code may looks as follows:

printmessages(){
    /* while loop */
    int i = 0;
    while ( i < length (messages) ){
        print (messages[i]);
        i ++;
    }
    /* for loop */
    for ( i = 0; i < length (messages); i++ ){
        print (messages[i]);
    }
    /* foreach loop */
    for ( string current : messages ){
        print (current);
    }
}

Please note you need to declare the index for a for loop before the loop header like i in our example.

Hash maps

Hash maps map one element of an arbitrary type to an element of another or the same type. You can also think of a table instead of a map. Let’s use another message routing protocol: Every node shall have two tables. One table contains the the distance to any destination node in number of steps to pass in the network, we call them hops. The other table one contains the next hop to take to an destination. Every node shall initially fill that table with its neighbors and inform them every time it finds a new shortest path to any node.

A hash map h from type K to type V can be declared as follows: [K,V] h;. Assigning values to it, reading its values or deleting a key can be done as in an array: h[k]=v; print(h[k]); h<[k]<; There is also a check contains for hash maps.

You can use a foreach for hash maps to, just declare two variables, one for the key and one for the value, as follows:

[string, string] map;
for (string key : string value : map){
    ...
}

Combining this thoughts, the complete code for a grid node may looks as follows. For readability this is reduced to the essential functionality.

gridNode{
    int size = 5; int x_this; int y_this;
    node top blue; node left yellow;
    node bottom red; node right green;
    [int,node] nextHop ignore hidden;
    [int,int] distance;
    message (string text, int to_id){
        if (to_id==id(this)) {
            print("Message " + text + " received.");
        } else {
            if (nextHop[to_id] == null){
                /* messages shall not be lost, so delay */
                this -> message (text, to_id);
            }
            nextHop[to_id] -> message (text, to_id);
        }
        mark (true);
    }
    updateDistance(int dst, int newDistance, node newNextHop){
        if (!containts(nextHop, dst) |
                            distance[dst] > newDistance){
            nextHop[dst] = newNextHop;
            distance[dst] = newDistance;
            right -> updateDistance(dst, newDistance+1, this);
            top -> updateDistance(dst, newDistance+1, this);
            left -> updateDistance(dst, newDistance+1, this);
            bottom->updateDistance(dst, newDistance+1, this);
            /* for the case this call is faster than entry */
            entry (newNextHop);
        }
    }
    entry(node n){
        int x_n=(id(n)-1)/size; int y_n=(id(n)-1)%size;
        if (x_n == x_this+1 & y_n == y_this) right=n;
        if (x_n == x_this & y_n == y_this+1) top=n;
        if (x_n == x_this-1 & y_n == y_this) left=n;
        if (x_n == x_this & y_n == y_this-1) bottom=n;
        updateDistance(id(n), 1, n);
        /* take care of race conditions */
        for (int dstNode : int nodeDistance : distance){
            n -> updateDistance(dstNode,nodeDistance+1,this);
        }
    }
    timeout(){
        mark(false);
    }
    init(){
        x_this=(id(this)-1)/size; y_this=(id(this)-1)%size;
    }
}

Challenge

We assume the node positions are fixed by the beginning. To achieve this, create a graph, turn of auto position and store that graph. Alternatively you can use this prepared graph file (right click the link and select “Save as”).

Here are two challenges for that:

  • Change the example above such that it doesn’t use hops but the sum of distances in the visualization.
  • Don’t store the nodes in variables left, top, bottom, right but in a list such that this program can be used to route in any kind of graph. Test it by creating some random bidirected graphs, not just grids, and send messages in that graph.

Previous: Data types, variables, and operations Next: String Operations

The University for the Information Society