by Arne Sommer

# 132 Lists with Raku

[216] Published 25. December 2022.

This is my response to The Weekly Challenge #196.

## Challenge #196.1: Pattern 132

You are given a list of integers, `@list`.

Write a script to find out subsequence that respect `Pattern 132`. Return empty array if none found.

Pattern 132 in a sequence (a[i], a[j], a[k]) such that `i < j < k and a[i] < a[k] < a[j]`.

Example 1: ```Input: @list = (3, 1, 4, 2) Output: (1, 4, 2) respect the Pattern 132. ``` Example 2: ```Input: @list = (1, 2, 3, 4) Output: () since no susbsequence can be found. ``` Example 3: ```Input: @list = (1, 3, 2, 4, 6, 5) Output: (1, 3, 2) if more than one subsequence found then return the first. ``` Example 4: ```Input: @list = (1, 3, 4, 2) Output: (1, 3, 2) ```

File: pattern132 ```#! /usr/bin/env raku unit sub MAIN (*@list where @list.elems > 0 # [1] && all(@list) ~~ /^<[1..9]><[0..9]>*\$/); my \$end = @list.elems - 1; # [2] for 0 .. \$end - 2 -> \$i # [3] { for \$i + 1 .. \$end - 1 -> \$j # [4] { for \$j + 1 .. \$end -> \$k # [5] { if @list[\$i] < @list[\$k] < @list[\$j] # [6] { say "(@list[\$i], @list[\$j], @list[\$k])"; # [6a] exit; # [6b] } } } } say "()"; # [7] ```

[1] A slurpy array, with at least one element. I have decided to allow posittive integers only, as the examples stick to that subset of the integers mentioned in the challenge.

[2] The index of the last element, as we use it in the three loops below.

[3] The `i` value can span the entire index range, except the last two - as we have to leave room for `j` and `k`.

[4] The `j` value starts right after `i`. We stop one index short of the edge, leaving room for `k`.

[5] The `k` value takes whatever is left, and iterates over those indices.

[6] Check if the values with the given indices satisfy the Pattern 132 rule. If they do, print the values [6a] and exit [6b]. If not, do nothing. I.e. go on.

[7] We come here if none of the iterations caused a match (and thus a program termination caused by `exit`). This means a failure, so we print the required empty parens.

Running it:

```\$ ./pattern132 3 1 4 2 (1, 4, 2) \$ ./pattern132 1 2 3 4 () \$ ./pattern132 1 3 2 4 6 5 (1, 3, 2) \$ ./pattern132 1 3 4 2 (1, 3, 2) ```

Looking good.

## Challenge #196.2: Range List

You are given a sorted unique integer array, `@array`.

Write a script to find all possible `Number Range` i.e [x, y] represent range all integers from `x` and `y` (both inclusive).

Each subsequence of two or more contiguous integers

Example 1: ```Input: @array = (1,3,4,5,7) Output: [3,5] ``` Example 2: ```Input: @array = (1,2,3,6,7,9) Output: [1,3], [6,7] ``` Example 3: ```Input: @array = (0,1,2,4,5,6,8,9) Output: [0,2], [4,6], [8,9] ```

File: range-list ```#! /usr/bin/env raku unit sub MAIN (*@array where @array.elems > 1 # [1] && all(@array) ~~ /^<[0..9]>+\$/ # [2] && [<] @array); # [3] my @ranges; # [4] my \$from = @array.shift.Int; # [5] my \$to = \$from; # [6] while @array # [7] { my \$next = @array.shift.Int; # [8] if \$next == \$to + 1 # [9] { \$to = \$next; # [9a] } else # [10] { @ranges.push([\$from, \$to]) if \$to > \$from; # [10a] \$from = \$to = \$next; # [10b] } } @ranges.push([\$from, \$to]) if \$to > \$from; # [11] say @ranges.raku; # [12] ```

[1] At least two elements.

[2] All of them must be non-negative integers, even if the challenge does not explicitly exclude negative values.

[3] The list must be sorted, in ascending order. The Reduction Metaoperator `[]` is ideal here.

See docs.raku.org/language/operators#Reduction_metaoperators for more information about the Reduction Metaoperator `[]`.

[4] The result (a list of ranges) will end up here.

[5] Get the first value. The trailing `.Int` coercer gets rid of the pesky `IntStr` type, which we get courtesy of the command line input.

See docs.raku.org/type/IntStr for more information about the `IntStr` type.

[8] The last value of the current range. This is initially the same as the start value, giving a range of one value - which is not a range at all.

[7] As long as we have unfinished business (i.e. values yet to be parsed).

[8] Get a new (unparsed) value.

[9] Does the new value fit in as thevery next value in the current range? If so, adjust the upper limit of the range accordingly.

[10] If not, add the current range to the result - if it is a range (e.g. if the start and end values differ) [10a], and initialise the current range with the new start value.

[11] When we are finished parsing the values, add the current range to the result list - if it is a range.

[12] Print the result using the `raku` method to give a readable output.

See docs.raku.org/routine/raku for more information about the `raku` method.

```\$ ./range-list 1 3 4 5 7 [[3, 5],] \$ ./range-list 1 2 3 6 7 9 [[1, 3], [6, 7]] \$ ./range-list 0 1 2 4 5 6 8 9 [[0, 2], [4, 6], [8, 9]] ```

Looking good. Except the extra brackets (and the trailing comma for the first one), but that is just a presentation quibble...

And that's it.