Switch the screen on/off Go back to last page Go forward one page Find out more details about the advertisement
John Moores University. Main CWIS Site
  

 Return to map_list 

Make_Variables

Below is a rather nice variable generator program. We may wish to generate say, 20 variables of the form x01, x02, ... , x20. Note, here, the importance of the leading 'zeros' for the first 9 variables. The same principle applies for 100 variables: x001, x002, ..., x100 and so on. In Derive, and in the easier make_variables function described elsewhere, Derive automatically removes any leading zeros. We want to keep them! Such variables are particularly useful, for example in Neural Networks, where it is common to have, say, 60 or more such variables.

Consider the following function make_variables:

MAKE_VARIABLES(vars, n, p_of_10, var_list, counter, v_, prefix, p10) :=
  Prog 
    vars := STRING(vars) 
    p_of_10 := FLOOR(LOG(n, 10)) 
    prefix := ITERATE(INSERT(0, v_, 0), v_, vars, p_of_10) 
    var_list := [] 
    counter := 1 
    p10 := 1 
    Loop 
      If counter = 10^p10 
        Prog 
          prefix := DELETE(prefix, -1) 
          p10 :+ 1 
      If counter > n 
        RETURN var_list 
      var_list := APPEND(var_list, [INSERT(counter, prefix, 0)]) 
      counter :+ 1

The list of arguments is self-explanatory, except for: vars - variables: p_of_10 - power of 10: var_list - variable list: v_ - some vector v: and p10 - another counter.

The first prog line, vars := string(vars), tells Derive we want the variables vars to be of data type string. This is the nitty-gritty, as we are saying: the first variable is a string x001, etc; NOT a normal variable x1.

p_of_10 := floor(log(n, 10)). As we count in denary, and the leading zeros need to be padded out in units of 10, so we need to calculate logs to base 10. p_of_10 simply calculates the exponent necessary to find out how many leading zeros are required.

prefix := iterate(insert(0, v_, 0), v_, vars, p_of_10) inserts a '0' in vector v_, at position '0'. This is repeated 'power_of_10' times. prefix, as the name suggests, represents the leading zeros.

We start off with the empty vector, var_list := [].

'counter' and 'p10' are both counters, initialised to 1.

The loop is perhaps more easily understood by reading 'bottom to top'. var_list := APPEND(var_list, [INSERT(counter, prefix, 0)]) effectively creates the list of variables, appending an extra variable each time the loop is passed through, subject to counter > n
The inner prog effectively deletes the last element (i.e. -1)each time the loop is entered, subject to LOG(counter, 10) = p10. Hence, as the the upper limit of variables increases by an extra digit, so the leading zeros correspondingly decrease.

So:

MAKE_VARIABLES(x,20)

[x01,x02,x03,x04,x05,x06,x07,x08,x09,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20]

 

An alternative to the above, which may or may not be faster in practice [see Debugging], although perhaps not as easy to read (particularly the var_list:= line, within the loop): 

MAKE_VARIABLES(vars, n, p_of_10, var_list, counter, v_) := 
  Prog 
    vars := STRING(vars) 
    p_of_10 := FLOOR(LOG(n, 10)) 
    var_list := [] 
    counter := 1 
    Loop 
      If counter > n 
        RETURN REVERSE(var_list) 
      var_list := ADJOIN(INSERT(counter, ITERATE(INSERT(0, v_, 0), v_, vars, p_of_10 - FLOOR(LOG(counter, 10))), 0), var_list)
      counter :+ 1

This is typed in the Entry line as:

MAKE_VARIABLES(vars, n, p_of_10, var_list, counter, v_) := PROG(vars := STRING(vars), p_of_10 := FLOOR(LOG(n, 10)), var_list := [], counter := 1, LOOP(IF(counter > n, RETURN REVERSE(var_list)), var_list := ADJOIN(INSERT(counter, ITERATE(INSERT(0, v_, 0), v_, vars, p_of_10 - FLOOR(LOG(counter, 10))), 0), var_list), counter :+ 1))

Sometimes however one can use a sledgehammer to crack a nut and a little lateral thinking with some insight, all the lines of code above can be condensed into a single line.  This 'improvement' comes from the 'mighty' Johann Wiesenbauer .

make_variables(x, n) := MAP_LIST(REPLACE(STRING(x), STRING(k + 10^DIM(n))), k, n)

REPLACE(x,v,n) replaces the contents of the nth element of v with x, were the default for n is 1.
  So
REPLACE(STRING(x),STRING(1005))="x005"
DIM(n)
were n is a number does the same job as FLOOR(LOG(n,10))+1.  The rest I'll let you sort out.