Raku challenge week 71

Solving the tasks of Week 71: Finding peak elements and Removing the item from a linked list.

This week, there were two different tasks:

Peak elements

In a given list of integers, find the elements that are local maxima.

Let us first generate an array of random integers:

my $n = 20;
my @data = map {50.rand.Int}, ^$n;
say @data;

Now, loop over the elements (skipping the edges) and testing if the current element is bigger than its neighbours:

my @peaks = map {@data[$_]}, grep {
    @data[$_ - 1] < @data[$_] > @data[$_ + 1]
}, 1 .. $n - 2;
say @peaks;

Remove element from a linked list

From a singly-linked list of integers, remove the Nth element from the end.

An additional comments in the task were: a) The last element has number 1, and b) if N-1 exceeds the size of the list, remove the head element.

My solution is demonstrated below. It is a single MAIN function that takes the size of the array and the above-mentioned N:

unit sub MAIN(Int $N is copy where * > 0 = 3, Int $size where * > 0 = 10);

OK, let is think how we can store singly-linked list in Raku.

class Node {
    has $.data;
    has $.next is rw;
}

Now, generate a random list:

my $head;
$head = Node.new(data => 100.rand.Int, next => $head) for ^$size;

say $head;

Note that we are generating the list from its tail, adding a new element before it on each iteration. That does not matter as the values are random.

Although we know the size of the list, it is assumed that the list is generated outside of the program, so let us count the elements ourselves:

my $length = 1;
my $curr = $head;
$length++ while $curr = $curr.next;

Now, it is time to find the element to be removed. If we have big enough N, then the task is trivial:

if $N >= $size {
    $head = $head.next;
}

For other Ns, there is only possibility to scan the list again until we reach the element number size–N.

else {
    $N--; # Input "1" means the element with 0 offset from the end;
    $N = $size - $N; # Count from the end
    $curr = $head;
    my $prev = Nil;
    while --$N {
        $prev = $curr;
        $curr = $curr.next;
    }
    $prev.next = $curr.next;
}

It’s all done, just print the result:

say $head;

A test run of the program so that you can see that it works:

$ raku ch-2.raku 3 5

Node.new(data => 9, next => Node.new(data => 13, next => Node.new(data => 24, next => Node.new(data => 82, next => Node.new(data => 10, next => Any)))))

Node.new(data => 9, next => Node.new(data => 13, next => Node.new(data => 82, next => Node.new(data => 10, next => Any))))

Links

GitHub repository
Navigation to the Raku challenges post series

Leave a Reply

Your email address will not be published. Required fields are marked *