with Raku

This is my response to The Weekly Challenge #196.

You are given a list of integers,

Write a script to find out subsequence that respect

Pattern 132 in a sequence (a[i], a[j], a[k]) such that

Example 1:

`@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.

You are given a sorted unique integer array,

Write a script to find all possible

Each subsequence of two or more contiguous integers

Example 1:

`@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.