Unusual features of Numipulator
Numipulator has a number of unusual, interesting features. These are ones concerned with the numipulation boxes.
Item-by-item handling and cycling
In many types of numipulation box, lists are handled item by item. This makes Numipulator very convenient for handling many numbers when you wish to carry out the same operation on each. So, for example, the Items Operation numipulation box carries out the same operation on corresponding items in two lists to give the resulting list, as shown in the first example below. If the second list consists of just one item, it will carry out the same operation using this number on each of the items in the first list, as shown in the second example below.
Now, for a true item-by-item operation, the two lists should have the same number of items to work on. But, in fact, as seen in the second Items Operation example above, we can have several items in the first, but only one in the second. This is because Numipulator allows cycling of items, as explained next.. Note: the labels for these item lists are generally shown with square brackets around them, e.g. [a] and [b]
The first list is treated as the primary item list (denoted here by the single quote after the [a]). If there is more than one list of items, one of these - and it's always the top one - is treated as the primary item list. The second list, and maybe others, are treated as secondary item lists, denoted by the double quote after the [b]. The primary item list determines the number of operations carried out, since the operation is carried out on each of its items in turn. The secondary items are taken one at a time to be used in these operations; if the end of a secondary item list is reached but there are still items in the primary list to be dealt with, items are selected from the beginning of the secondary list again. That is, the secondary items are cycled to match the primary items.
To demonstrate, suppose the primary list, has values 2, 4, 6, 8 - that is, 4 items. Let's look at what happens if a secondary item list has 1, 2, 3, 4 or 5 items in it.
The common cases, where there is just one item in a secondary item list or the same number as in the primary item list, can be seen to be special cases of this general approach to handling more than one item list.
Although lists and numbers are the only core object types in Numipulator, some numipulation boxes are designed to perform operations on or transformations of a table. In such cases, the input table is always defined by two inputs: a list and a number (a positive integer).
So, the input table
1 2 3 4
would be represented by la=1, 2, 3, 4, 6, 3, 2, 7, 8, 9, 0, 1 and ncols=4
The number of rows in the table is, of course, implied by la and ncols.
Because the only core object types in Numipulator are lists and numbers, a table cannot be the result of a numipulation box. However, the list of cell values can, of course, be given as the result. So, for example, if the above input table had its rows and columns transposed in an operation, giving the table
1 6 8
the result would be given as the list of cell values (starting at the top row and always going left-to-right):
1, 6, 8, 2, 3, 9, 3, 2, 0, 4, 7, 1
Note: Numipulator uses the number of columns as a parameter (rather than number of rows) because tables of data in spreadsheets are generally designed to have a fixed number of columns, but a variable number of rows, so, when handling a table, the number of columns is generally a given. Numipulator bases its handling of a table where la is an empty list accordingly, i.e. treating the input table as still having a given number of columns, but no values in these (i.e. 0 rows). So, if la=L0 (this is the Numipulator for an empty list, with no items on it) and ncols=3, the sums of its columns would be 0, 0, 0 (3 columns, each with a sum of 0), while the sums of its rows would be L0 (an empty list, as there are no rows).
Handling numerical expressions
The Number Operation numipulation box handles just one operation between two numbers. Strictly, this is adequate for all operations you might need to perform, but linking several of these to evaluate a more complex expression, e.g. 2 x 3 + 4 / 2, can be tedious. Numipulator therefore provides a feature that allows some more complex expressions to be evaluated in one numipulation box.
The Calculator function (found in the List Function to Number numipulation boxes) has as its single input a list that is treated as a combination of numbers and operator codes: codes representing Number Operations, e.g. +, -, x and /. The codes that represent the number operations are found by pressing the Codes link in Numipulator, but, in brief, 1 means add, 2 means subtract, 3 means multiply and 4 means divide, 5 means % - these are the order in which the operations are found in the drop-down list of Number Operations. The list starts with a Number, which is followed by any number of Operator code, Number pairs, i.e. Num, Op, Num, Op, Num... The list is evaluated from left to right, as if the numbers and operators were being entered into a standard calculator. So, 2 3 3 1 4 4 2 is treated as the Number/Operator list: 2 x 3 + 4 / 2, which means ((2 x 3) + 4) / 2, i.e. 5.
Alternatively, the Expression function takes the same input list, but instead of evaluating the operations from left to right, like a calculator, standard arithmetic operator precedence is employed (BODMAS/PEMDAS), where multiplication and division are carried out before addition or subtraction. So, the input list 2 3 3 1 4 4 2 is again treated as the Number/Operator list: 2 x 3 + 4 / 2, but this time it is taken to mean (2 x 3) + (4 / 2), i.e. 8.
As well as including operators in these expressions, number functions can also be included, through the use of the mock operator code 100. In this case, the number following 100 is treated as a number function code, similar to operator codes: 1 means square, 2 means square root, 3 means +/-, and so on. So, 4 100 1 1 pi means 42 x pi, as 4 100 1 means 4 squared.
Clearly, neither reading nor writing such expressions is easy. However, use may be made of Mappings for inputs, whereby symbols or words (with some exceptions) can be mapped to numbers and used instead of those numbers in inputs, if desired. So, if Mappings are defined as follows:
Handling logic expressions
The Number Operation numipulation box also includes a number of Check (1/0): operations. The (1/0) here indicates that the output can only be 1 or 0. So, the operation Check (1/0): a<b has the result 1 if a (the first input) is less than b (the second input), otherwise it has the result 0. Numipulator has no normal Boolean values (TRUE/FALSE), but uses 1/0 instead. In addition, the Number Operation box has a number of Logic (1/0): functions, such as Logic (1/0): a AND b and Logic (1/0): a OR b functions. These again produce results of only 1 or 0. Logic (1/0): a AND b produces the result 1 if both a and b are 1 or any non-zero value, or 0 otherwise. Logic (1/0): a OR b returns the result 1 if either a or b is non-zero, or 0 if both a and b are zero.
The Expression function can include these in the expressions it handles, again using certain integers (14-19 for the Check operations and 20-25 for the Logic operations) to specify these operations. As with the numerical expressions, the built-in Input Mappings may be employed to make these expressions more readable, so that the expression A1 < A2 AND A1 > 1 OR B1 = 5 OR 4 x B2 > 25 would be a valid expression. Note that arithmetic operations are carried out first, using BODMAS/PEMDAS precedence, followed by Check operations (<, =, >, etc.), then AND operations, and finally OR operations. The full meaning of this expression is therefore: ((A1 < A2) AND (A1 > 1)) OR (B1 = 5) OR ((4 x B2) > 25).
Numbers and lists - syntax and interchangeability
Numbers and lists of numbers are inherently different types. In most computing languages, they would be treated differently, and you would need to be careful to distinguish the two. In Numipulator, however, you may freely mix numbers and lists of numbers.
To explain what we mean by this, consider the following list input to a numipulation box:
Now, A1 is a reference name that refers to a number output (from a Number Operation), while L2 refers to the output from a Findall operation, which produces a list output. To determine what this input represents, we simply replace the reference names with the number or list of numbers that they represent. So, if A1 evaluates to the number 4 and L2 evaluates to the list of numbers 6, 7, then the list would have the value 1, 2, 3, 4, 5, 6, 7, 8. If A1 evaluates to 60 and L2 evaluates to the list with just one number, 70, on it, then the value of the input would be the list 1 2 3 60 5 70 8. One more option to consider is when A1 evaluates to 4 but L2 returns an empty list; in this case, the input has the value 1 2 3 4 5 8, as there are no numbers to insert between the 5 and the 8.
A reference name to a list numipulation box may also be used as an input when a single number is expected, e.g. to a Number Operation. In this case, the first or only number on the list is treated as the input number. This makes Numipulator very flexible, as it means that any numipulation box that has a list output with only one number on it may be used exactly as if it had a number output. So, given the Items Operation discussed above, if the first input were the single-item list 2 and the second input were the single-item list 3, then the output would be the single-item list 6, which could be used exactly as if it were the number output from a Number Operation. This means that in theory we could have omitted Number Operation boxes and Number Function boxes from Numipulator altogether, and just used the Items Operation and Items Function boxes instead. In practice, however, it was felt that the Number ... boxes were important, as single-number operations would be familiar to users. Likewise, we could have combined the List Function to Number boxes and the List Function to List boxes into a List Function box, with some outputs being always being single-item lists, but chose not to do so. As you will see in the next section, on If-Then-Else boxes, the outputs are always lists. Because these can be used as if they were number outputs, where appropriate, we chose not to include separate number output versions of these.
This flexibility means that inputs to lists are always simple, syntactically. In Numipulator, the programmer does not need to explicitly join (concatenate) two lists with a concatenation function; the programmer merely writes one after the other in an input, so that they are implicitly concatenated, e.g. L1 G4, which effectively means L1 concatenated with G4.
Because a list of numbers is written in the list box as simple numbers, it might be thought that an empty list would be specified as an empty box. However, the system checks for syntax errors before carrying out any calculations, and it is important that the system can determine which numipulation boxes are being used or are incompletely specified. A blank list box is taken to indicate that this input is not specified (deliberately or accidentally). Therefore, we enter the term L0 (meaning list of 0 length) to indicate that the input is an empty list. Likewise, L0 is written by Numipulator as the output if the result is an empty list, rather than just leaving the output field blank.
If-Then-Else numipulation boxes and Case functions
If-Then-Else boxes are an essential feature of Numipulator, as your program must be designed to produce new states and graphical output for all possible states and user interactions, and these provide the functionality to generate alternative outputs for the various input states and user inputs. There are four different types of If-Then-Else box. Each has four inputs: the first two are numbers or lists involved in some form of comparison defined in the drop-down list, while the last two define alternative outputs based on the results of the comparison.
The first two inputs (a and b) are simple numbers, and the comparisons are just <, <=, =, <>, >=, >. The last two inputs (lc and ld) are alternative list outputs.
The first two inputs ([a] and [b]) are item lists, with the usual item cycling. The comparisons are as above, but in this case the check is whether every comparison between the two corresponding items succeeds. The last two inputs (lc and ld) are alternative list outputs.
e.g. if all a < b: lc, else ld (other comparisons similar)
The first two inputs ([a] and [b]) are item lists, with the usual item cycling. Comparisons are <, <=, ... > as before. The last two inputs, [c] and [d], are also secondary item lists. In this case, the output list is made up of items from either [c] or [d], depending on whether the corresponding comparisons between the items on [a] and [b] succeed.
e.g. if a < b: c, else d (other comparisons similar)
The first two inputs (la and lb) are lists, and comparisons are made between la and lb as a whole, e.g. la=lb, or all la on lb (i.e. la is a subset of lb). The last two inputs, lc and ld, are alternative list outputs.
e.g. if la=lb, lc, else ld
Probably the most useful of the available functions in this box is if exp(la)=lb, lc, else ld. A simple use of this is to permit a complex logic expression to be specified in la, with lb being specified as 1 (to indicate that the expression should be true), or 0 (to indicate that it should be false). So, if la=A1 < A2 AND A1 > 1 OR B1 = 5 OR 4 x B2 > 25, lb=1, lc=20 and ld=30, then if A1 < A2 AND A1 > 1 OR B1 = 5 OR 4 x B2 > 25 is true (result = 1), then the result is 20, otherwise it is 30.
Numipulator also includes Case... functions in the List Function to Number numipulation boxes. These are useful if you wish to make a series of simple number comparisons and to have, as output, a single number based on these comparisons. There are six similar Case functions, e.g. Case: <, Case: <=, Case: =, and so on. The input is a single list of numbers, which should be considered in groups of three, leaving one additional number. If the selected comparison between the first and second items of the three succeeds, then the output is the third. If it fails, then the second group of three is checked likewise, until a result is found. If no result is found by checking the groups of three, then the additional number, the default, becomes the output.
e.g. Case: <
Other more complicated Case functions are also available.
Lack of features found in most other programming languages
The simplicity of Numipulator (particularly its simple syntax for input lists) comes at a price: Numipulator lacks many of the features and functionality found in most other languages or systems.
a. Numipulator does not provide special syntax to allow access to particular elements of lists, as you might in other languages where you might write A1 to return the 3rd element of list A1 (in many languages, the first element of a list has index 0). Instead, you must use the Item p1 operation (a List Operation), and make the first input A1 and the second 3. Using normal indexing (starting at 1) is clearly easier to understand, and you can put in several numbers in the second list, e.g. 3, 5, 7, which would have as its output a list with the 3rd, 5th and 7th items on the list.
b. Numipulator does not let you include mathematical expressions to be evaluated within a wider list, e.g. 1, 2, 18x2/12, 4, to yield the list 1, 2, 3, 4. You can, as described above, use the Expression or Calculator functions to evaluate and output such expressions.
c. While Numipulator provides a wide array of built-in numerical calculation and manipulation functions/operations, it does not provide you with the possibility of adding new or customized functions.
d. Numipulator does not provide variables that can be used to store values. It does offer Memory numipulation boxes that can effectively be used to remember values from one cycle to the next. These are quite different from variables, as the value of variables can be modified at any time during the running of a program in a procedural language. In contrast, the output of a Memory box is taken only after Function Evaluation has been completed for the cycle, and used to replace the input specification of the Memory box ready for any future cycle. Overall, with Numipulator, in any single Function Evaluation cycle every numipulation box and every internal value such as now and click has one value only.
e. Numipulator provides no procedural statements at all, such as print() or display(). The processing engine does, of course, print and display output, but it follows the same procedure every time; the programmer can influence this through settings and through values that are evaluated as part of the Function Evaluation, which influence the procedure: these values act as parameters for the procedure.
The simplified steps of this procedure are as follows for a program that uses the Graphics Formatter, after the Start button has been tapped to start a set of repetitions with a specified terminating condition:
Copyright TopAccolades Limited, 2023