Programming language J. Look amateur. Part 3. Arrays

  • Tutorial
Previous article in the programming language J. Look of an amateur. Part 2. Tacit programming

“I don’t think he suits us. I told him what we were doing, and he did not argue. He was just listening. ”
Ken Iverson after one of the interviews



1. Arrays



J is a language for processing arrays. There are many ways to create arrays in J. For instance:
  • "$" - this verb returns an array, the dimension of which is indicated in the left operand, and the contents in the right. Create an array of a given dimension, all of whose elements are the same:

    	3 $ 1   NB. создаем вектор с тремя элементами, каждый из которых = 1
    1 1 1
    	2 3 $ 2 NB. создаем матрицу из 2 строк и 3 столбцов, все элементы которой = 2
    2 2 2
    2 2 2
    


    You can also specify an arbitrary vector with the right operand, the elements of which will be sequentially copied to the resulting array:


    	2 3 $ 1 2 3
    1 2 3
    1 2 3
    	2 3 $ 1 2
    1 2 1
    2 1 2
    	2 3 $ 1 2 3 4
    1 2 3
    4 1 2
    

  • "#" - in the dyadic version, the copy verb. Copies the ith element of the right operand as many times as specified in the ith element of the left operand. Thus, the length of the resulting array is equal to the sum of the elements x. Example:

    	1 2 0 3 # 1 2 3 4
    1 2 2 4 4 4
    	4 # 1
    1 1 1 1
    

  • "I." creates listings and tables. In a monad call, it returns an array composed of integers (starting from zero), each of which is one greater than the previous one. The length of such an array is specified by the right operand. If the operand value is negative, then the numbers in the resulting array go in the reverse order:

    	i.4 NB. пробел между глаголом и операндом необязателен
    0 1 2 3
    	i._4
    3 2 1 0
    	i.2 3
    0 1 2
    3 4 5
    


Pay attention to the last example - the verb “i.” Returned a two-dimensional array to us, because the operand passed to him was a vector. The first element of the operand indicates the number of rows; the second, columns. However, using this verb you can get an n-dimensional array. For example, three-dimensional:


	i.2 _2 3
3  4  5
0  1  2
9 10 11
6  7  8


The rows in the resulting array go in reverse order, because the second dimension is given by a negative number. We'll talk more about multidimensional arrays in the next section.

Due to the fact that many standard verbs J are capable of processing arrays of data, it is possible to extend the verbs described earlier to the case of arrays.

	- 1 2 3
_1 _2 _3


Dyad case:

	1 2 3 - 3 2 1
_2 0 2


In addition, operations on different peer values ​​are acceptable:

	1 2 3 - 1
0 1 2


The same result can be obtained using the verb <:

	<: 1 2 3
0 1 2


The reverse operation is also acceptable:

	1 - 1 2 3
0 _1 _2


Recall that the last expression can also be written as “1 2 3 - ~ 1”.

In addition to standard arithmetic verbs, a verb generator of pseudorandom numbers “?” Is useful in our work. Being called with one operand "?" returns:
  • random floating-point number if the operand is zero;
  • random integer in the range from zero to y if the operand is equal to y.

	? 0 NB. конечно, у вас результат будет отличаться
0.622471
	? 3 NB. вернет случайное число на отрезке [0;2]
2
	? 3
0


You can set the pseudo-random number sensor using a call

	9!:1 y


The initial value of seed = 7 ^ 5.

As with all examples earlier in this section, the verb "?" can be called with an operand array - the result will be an array of the same dimension, each i-th element of which will be a random number on the interval specified by the i-th element of the operand:

	? 0 10 100
0.429769 7 95


The verb “?”, Of course, works not only with vectors, but also, for example, with matrices:

	? (2 2 $ 0 10)
0.084712 4
0.840877 1


2. Parts of speech for working with arrays



As we already know, J is a language for processing arrays. This is expressed, not least, in the fact that when working with arrays you practically do not have to use explicit iterative procedures.

Suppose you need to find the sum of all elements of a sequence in a subset of the Python language. We generalize this problem to the standard convolution function:

def reduce(xs, f, acc = 0):
   """Пример запуска:
        >>> reduce([1,2,3], lambda acc,x: acc + x)
        6"""
   for x in xs:
       acc = f(acc,x)
   return acc


To solve such problems, J has a special adverb "/" called "between." Indeed, our python function is equivalent to the following expression “x0 f x1 f ... f xN”. In terms of J, this is written as “f / xs”, where xs is the noun (vector), f is the verb that is inserted “between” the elements of the noun xs, “/” is the adverb that actually performs such a transformation. Here is an example:

	+/ 1 2 3 NB. аналогично «1 + 2 + 3»
6
	-/ i.3 NB. аналогично 0 - (1 - 2)
1


But what if we need to return as a result of the convolution not only the final result of the calculations, but also all the intermediate results (in the context of the Python source code, all the intermediate values ​​of the variable “acc”)? That is, for example, for the vector “1 2 3 4” after applying the verb “+” “between” it is expected to get “1 3 6 10”.

There is a special adverb “\” in J for this purpose:

	+/\ 1 2 3 4 NB. эквивалентно выражению: (1) , (1+2), (1+2+3), (1+2+3+4)
1 3 6 10
	-/\ 0 1 2   NB. эквивалентно выражению: (0), (0-1), (0-(1-2))
0 _1 1


Other necessary verbs are “/:” and “\:”, which sort the transmitted vector in ascending and descending order, respectively. Moreover, the result of sorting is a vector of indices of sorted elements:

	/: 1 3 2
0 2 1
	\: 1 3 2
1 2 0


In order to get the elements of an array using the indicated indices, we use the verb "{", which extracts the elements from the array (the right operand) at the indicated indices (the left operand). For instance:

	1 0 1 2 { 11 22 33 44
22 11 22 33


Other verbs for “manual” indexing of array elements are
  • "}." returns the "tail" of the array, i.e. all elements except the first.
  • "{." returns the "head" of the array, ie first element of the array.
  • "{:" Returns the last element of the array.
  • "}:" Returns all elements of the array except the last.


Recall the adverb “~”, which swaps the right and left operands in places, and gives a slightly more complex example:

	({~ /:) (? (5 $ 0))
0.221507 0.293786 0.691701 0.72826 0.839186


In this example, a sequence of 5 random real numbers is generated, then a hook from the verbs "{~" and "/:" is applied to the result.

3. Multidimensional arrays and ranks


We have already mentioned multidimensional arrays. It would be logical to assume that since standard verbs work both with numbers and with vectors of numbers, then they can also process multidimensional data arrays.

	]x =: i.2 3 NB. глагол ] возвращает свой правый операнд, т.е. в данном случае переменную x
0 1 2
3 4 5
	x + 10 20 30
|length error
	x + 10 20
10 11 12
23 24 25


As we can see, if you execute the standard verb on the matrix and the vector, then the default action is "by columns". In the example, “10” is added to the element on the first row of each column, and “20” is added on the second row. The dimension of the array in Example 2 is 3. We will say then that the first rank of this array is 2 and the second rank is 3. Since the verb is applied to the columns of the matrix by default, we can say that it is applied to the second rank.

This is a general rule for J - verbs are applied by default to the extreme rank of the array. In order to explicitly indicate the rank of a verb, a special union "" "(double quotes) is used, which takes a verb with the left operand and rank (an integer) with the right operand. For example:

	(i.2 3) + 10 20
10 11 12
23 24 25
	(i.2 3) +"2 (10 20)
10 11 12
23 24 25


As you can see, these two expressions are equivalent. Note the brackets around the vector (10 20). If they are not set, then the translator J will assume that the rank of the verb is “2 10 20”, and the right operand of the verb is not specified. In order not to explicitly indicate the rank of the verb, it is recommended to use the infinity sign "_":

	(i.2 3) +"_ (10 20)
10 11 12
23 24 25


The result of this will not change. If you change the rank of the verb to 1:

	(i.2 3) +"1 (10 20)
|length error


The error of this expression is that we are trying to apply the summation verb to a vector of length 2 (the right operand) and to a row vector of the left operand of length 3. Let's change our example a bit:

	(i.2 3) +"1 (10 20 30)
10 21 32
13 24 35


The result corresponds to the sequential summation of the ith element of the right operand and each ith element of each row of the left operand.

The final article in the series J. Programming Language. Part 4. Boxes and cycles. Conclusion

Also popular now: