On this page:
6.3.1 Exercises 30
6.3.1.1 Question 94
6.3.1.2 Question 95
6.3.1.3 Question 96
6.3.1.4 Question 97
6.3.1.5 Question 98
6.3.1.6 Question 99
6.3.1.7 Question 100
6.3.1.8 Question 101
6.3.1.9 Question 102

6.3 Enumerations

We saw that arrays can be sliced using a range of indexes, starting at a number and ending in another. The range of indexes represents all integers between those two limits. The elements in a range can be enumerated, by considering that, given the limits \(a\) and \(b\) of an interval \([a, b]\) and an increment \(i\), we obtain an array containing the numbers \(a\), \(a+i\), \(a+2i\), \(a+3i\), \(a+4i\), ..., up to \(a+ni \geq b\).

We can take advantage of recursion to implement this idea: the enumeration of the numbers in the interval \([a, b]\) with an \(i\) increment is exactly the same as the number \(a\) followed by the enumeration of the numbers in the interval \([a + i, b]\). If we repeat this process a sufficient number of times, we reach the simplest case of all: an enumeration in the interval \([a, b]\) wherein \(a>b\), whose result is an empty array.

This description can now be translated into the function’s definition:

enumerate(a, b, i) = a > b ? [] : [a, enumerate(a+i, b, i)...]

As an example:

> enumerate(1, 5, 1)

5-element Vector{Int64}:

 1

 2

 3

 4

 5

> enumerate(1, 5, 2)

3-element Vector{Int64}:

 1

 3

 5

To make the function even more generic, we should also cover the case where \(i\) is a negative increment, which is useful, for example, for a regressive counting.

The current definition of the enumerate function does not support regressive counting, because the use of a negative increment causes infinite recursion. The problem lies in the stopping condition: the operator > is only suitable for the case in which the increment is positive. When the increment is negative, we should use <. So, to solve this problem, the function must identify the correct enumeration to use:

enumerate(a, b, i) =

  let enumerate_up(a) = a > b ? [] : [a, enumerate_up(a+i)...],

      enumerate_down(a) = a < b ? [] : [a, enumerate_down(a+i)...]

    i > 0 ? enumerate_up(a) : enumerate_down(a)

  end

Now we can have:

> enumerate(1, 5, 1)

5-element Vector{Int64}:

 1

 2

 3

 4

 5

> enumerate(5, 1, -1)

5-element Vector{Int64}:

 5

 4

 3

 2

 1

> enumerate(6, 0, -2)

4-element Vector{Int64}:

 6

 4

 2

 0

The function enumerate describes an operation that is so common that Julia already provides support for it: the range expression start:step:stop represents an abstract enumeration. When the increment step is one, it can be omitted. To collect the elements of an enumeration in an array, we can use the function collect:

> collect(1:2:4)

2-element Vector{Int64}:

 1

 3

> collect(1:4)

4-element Vector{Int64}:

 1

 2

 3

 4

6.3.1 Exercises 30
6.3.1.1 Question 94

The \(iota\) function is an enumeration starting at \(0\) and ending at the upper limit \(n\), excluding the \(n\) value, containing the elements of the enumeration separated by a given increment. For example:

> iota(10, 1)

10-element Vector{Int64}:

 0

 1

 2

 3

 4

 5

 6

 7

 8

 9

> iota(10, 2)

5-element Vector{Int64}:

 0

 2

 4

 6

 8

Define the iota function using the enumerate function.

6.3.1.2 Question 95

Redefine the iota function using collect and a range.

6.3.1.3 Question 96

Define a function called ismember that receives a number and an array, and then checks whether that number exists in the given array. Here are two examples of the use of the function:

> ismember(3, [5, 2, 1, 3, 4, 6])

true

> ismember(7, [5, 2, 1, 3, 4, 6])

false

6.3.1.4 Question 97

Define the function eliminate1 that receives a number and an array, and returns an identical array without the first occurrence of that number. Here is an example:

> eliminate1(3, [1, 2, 3, 4, 3, 2, 1])

6-element Vector{Int64}:

 1

 2

 4

 3

 2

 1

6.3.1.5 Question 98

Define a function called eliminate that receives a number and an array, and returns an identical array without any occurrence of that number. Here is an example:

> eliminate(3, [1, 2, 3, 4, 3, 2, 1])

5-element Vector{Int64}:

 1

 2

 4

 2

 1

6.3.1.6 Question 99

Define a function called replace that receives two numbers and an array, and returns an identical array with all the occurrences of the second argument replaced with the first argument. Here is an example:

> replace(0, 1, [1, 2, 1, 3])

4-element Vector{Int64}:

 0

 2

 0

 3

> replace(0, 1, [2, 3, 4, 5])

4-element Vector{Int64}:

 2

 3

 4

 5

6.3.1.7 Question 100

Define a function called remove_duplicates that, given an array of numbers, returns an identical array without the repeated numbers. Here is an example:

> remove_duplicates([1, 2, 3, 3, 2, 4, 5, 4, 1])

5-element Vector{Int64}:

 3

 2

 5

 4

 1

6.3.1.8 Question 101

Define a function called occurrences that, from a number and an array, returns the number of times that number appears in the array. Here is an example:

> occurrences(4, [1, 2, 3, 3, 2, 4, 5, 4, 1])

2

6.3.1.9 Question 102

Define a function called position that receives a number and an array as arguments and returns the position of the first occurrence of the number in the array. Note that positions in an array start at one. For example:

> position(4, [1, 2, 3, 3, 2, 4, 5, 4, 1])

6