📘 Increasing sequences in Perl 6

Check if the given array contains increasing (or decreasing) numbers.

Given the list of numbers in an array, the task is to tell if all of them are sorted in ascending or descending order.

Take an array:

my @data = 3, 7, 19, 20, 34;

In Perl 6, reduction operators offer a very expressive and simple way to find the answer in one go:

say [<] @data;

With the values listed above, this program prints True. Change the array to break the increasing sequence, and the program prints False.

You will not be surprised to find out that to check whether the array is sorted in decreasing order, the code is as follows:

say [>] @data;

Using reduction operators is equivalent to inserting the main operator between the elements of the array, so [<] @data is the same as the following chain of comparison operations:

say @data[0] < @data[1] < @data[2] < @data[3] < @data[4];

By the way, Perl 6’s ability to understand chained operations is very handy in the if conditions, for example:

my $x = 15;
say 'ok' if 10 < $x < 20;

📘 Finding minimum and maximum using Perl 6

Find the minimum and the maximum numbers in the given list of integers.

Finding the minimum and maximum elements of arrays is extremely easy in Perl 6. For iterable objects, the two methods, min and max, are defined.

my @list = 7, 6, 12, 3, 4, 10, 2, 5, 15, 6, 7, 8, 9, 3;

say @list.min;
say @list.max;

For the list in the example, this program prints two numbers:

2
15

The min and max routines can be used as binary operators, in which case they return the smaller or the bigger number:

say 7 min 8; # Prints 7
say 7 max 8; # Prints 8

Operators can be chained like this:

say 7 min 5 min 8; # Prints 5
say 7 max 5 max 8; # Prints 8

This can be expressed with the help of a reduction meta-operator […]:

say [min] 7, 9, 5; # Prints 5
say [max] 7, 9, 4; # Prints 9

Lists are also accepted, for example: say [min] @list.

📘 Finding unique elements using Perl 6

Print all unique elements of the given array.

In Perl 6, objects of the Array type have the unique method.

my @a = 2, 3, 7, 4, 5, 5, 6, 2, 10, 7;
say @a.unique;

The result of running this program is a sequence containing the unique elements: (2 3 7 4 5 6 10).

Notice that the values are not sorted and appear in the same order as they first appeared in the original data, which stays unchanged.

The routine can be used as a function:

say unique(@a);

It can also take a code block or a reference passed via the with named argument to replace the default comparison method. The following example demonstrates how to select rational numbers that only repeat once within the given integer part.

<1.1 1.3 2.2 2.5 3.6>.unique(with => {
    $^a.Int == $^b.Int;
}).say;

From the given list of numbers, only three pass the filter: (1.1 2.2 3.6).

The $^a and $^b are the placeholder variables that receive pairs of values when the with code block is activated. Alternatively, arguments with explicit names may be used:

unique(@data, with => -> $x, $y {$x.Int == $y.Int}).say;

📘 Counting the number of occurrences in array using Perl 6

Count how many times a particular element appears in the array.

Let’s have an array with a list of fruits; some of them are repeated.

my @data = <
    apple       pear      grape     lemon
    peach       apple      banana   grape 
    pineapple  avocado
>;

Now, the task is to count how many times the element 'grape' appears there. First, extract all the elements to a temporary array by using the grep method, and then call the elems method to get the number of elements in the filtered data.

my $n = @data.grep('grape').elems;
say $n; # 2

Notice also a very handy way of defining arrays of strings. Instead of quoting all the elements, use the <...> syntax to create a list out of space-separated values. 

If you need to determine the number of occurrences for more than one element, then it is better to use the more efficient technique to avoid grepping the array for every item.

my %count;
%count{$_}++ for @data;

say %count<pineapple>; # 1
say %count<grape>;     # 2

📘 Taking every second element using Perl 6

Form a new array by picking every second element from the original array.

There is an array of numbers, and the task is to pick every second element and put them into a new array.

Prepare the test data:

my @data = 20..30;

Here is a possible solution:

my @selected = @data[1, 3 ... *];
say @selected;

This program prints the following values:

[21 23 25 27 29]

We are using a slice to provide the needed indices within the pair of square brackets. To make a slice, just list more than one element inside the brackets, for example:

say @data[2, 3, 5]; # (22 23 25)

To select every second element, a sequence 1, 3...* is created. The ... sequence operator creates a sequence based on the example list provided on its left side. The two numbers, 1 and 3, provide a pattern for the arithmetic progression; thus, every element is calculated as xn = x(n-1) + 2.

The star at the right end of the sequence ensures that the sequence is generated until the whole array has been looked up. Using the * is a very Perl 6-ish way to ask the compiler to do the right job for you (the Do What I Mean, or DWIM, principle).

📘 Finding the first odd number using Perl 6

Find the first odd number in a list of integers.

The task is to find the first odd number in a given list of odd and even numbers. A good candidate is the firstroutine, which searches for the leftmost value (see, for example, Task 58, Is an element in a list?). Now, we can pass an anonymous code block to it to calculate the predicate.

my @nums = (2, 4, 18, 9, 16, 7, 10);
my $first = @nums.first: * % 2;
say $first; # Prints 9

Colon syntax is used here to pass arguments to methods. The same call may be written in the traditional style with parentheses:

my $first = @nums.first(* % 2);

The construction with a star (which is called Whatever) creates a code block with one argument, equivalent to {$a % 2}, that returns True when the number is odd. The same code can be rewritten less efficiently with a grep:

my @odd = grep {$_ % 2}, @nums;
say @odd[0]; # Prints 9

Let us try another method by matching the value against a regex that tests whether the last digit of a number is odd:

@nums ~~ /(\d*<[13579]>$)/;
say $/[0];

The whole array is matched against the regex, and the first captured value is printed.

📘 Check if an element is in a list in Perl 6

Tell if the given value is in the list.

There are a few approaches to the problem. The most compact one seems to be the use of the smartmatch ~~ operator in combination with the anyfunction:

my @array = (10, 14, 0, 15, 17, 20, 30, 35);
my $x = 17;
say 'In the list' if $x ~~ any @array;

To check if a given value is contained among the elements of an array or a list, use the greproutine.

say 'In the list' if grep $x, @array;

The grep routine returns a list of all the matched elements. In the Boolean context, the return value is True if at least one element was found. In the opposite case, an empty list coerces to False. If the element in question is not zero, then the first routine may be used instead of grep. It returns the first element that matches the search pattern:

say 'In the list' if first $x, @array;

To extend this to zero values, test the values before making a decision:

say 'In the list' if $x == first $x, @array;

Another solution is to convert the array to a hash and check if there is a key with the given value. This is useful when you need more than one check.

my %hash = map {$_ => 1}, @array;
say 'In the list' if %hash{$n};