Archive

Archive for September, 2021

Convolution

September 24, 2021 1 comment

Flavio wrote a straightforward solution to PWC-131-1 and wondered if there is a idiomatic way. Assuming, that “idiomatic” means to use language features which lesser languages refuse to require, I’m happy to deliver convoluted code.

use v6.d;

sub consecutive-a(*@a) {
    my @ret;

    gather {
        for (|@a, |@a.tail).rotor( 2 => -1 ) -> [$a, $b] {
            @ret.push: $a;
            unless $b == $a + 1 {
                take @ret;
                @ret = [];
            }
        }
    }
}

sub consecutive-b(*@a) {
    my @gaps = @a.rotor(2 => -1).kv.grep(-> $index, [$a, $b] { $b !== $a + 1 })[*;0];
    return @a unless @gaps;
    @gaps = (@gaps Z @gaps »+» 1).flat;
    my $ranges := (0, @gaps, (@a - 1)).flat.map(-> \l, \r { l .. r });

    @a[$ranges]
}

sub MAIN() {
    my @examples := (1, 2, 3, 6, 7, 8, 9)
                  ,(11, 12, 14, 17, 18, 19)
                  ,(2, 4, 6, 8)
                  ,(1, 2, 3, 4, 5);

    .&consecutive-a.say for @examples;
    say();
    .&consecutive-b.say for @examples;
}

Both exibits use .rotor to create easily comparable pairs of numbers. The first variant uses gather/take to return the by PWC requested sublists lazily. If we spot a gap take the list and empty the Array-container. If numbers are consecutive we add them to the return buffer. The laziness may help with very large lists.

The 2nd version creates a list of gaps. Since we can’t point in-between two elements, we first take the last index of the last element of a sub-list and then zip the following element, hoping the Array not to contain holes. The first and last index of @a are added. We now have a list of begin- and end-indices of the sub-lists. Those are composes to Range-objects. Such a list (Rakudo doesn’t like an Array in this case) can be used in Positional-subscripts to gain the desired sub-list of consecutive Ints. This solution can take a shortcut if no gaps are found.

I’m not entirely sure if this is better then a boring way to solve the task. It does provide a reason for another blog post, though. Quite helpful to reach 150 posts before the end of the year.

Categories: Raku

Calling by name

September 3, 2021 1 comment

While looking for something completely different, I found that Roast really likes named callable placeholder variables.

dex@dexhome:~/projects/raku/roast$ ack -l  '&\:'
S02-names/SETTING-6c.t
S02-names/SETTING-6e.t
S02-names/pseudo-6c.t
S02-names/pseudo-6d.t
S02-names/pseudo-6e.t
S02-names/symbolic-deref.t
S06-operator-overloading/infix.t
S06-signature/closure-parameters.t
S32-num/rounders.t
integration/advent2013-day10.t
integration/weird-errors.t

That is hardly a surprise, given that the specs are composed of short snippets of code. Placeholder variables fit right in!

sub foo { "Good &:greeting(now.DateTime.hour) $:name!" };
say foo :name<Paul>, :greeting{$_ < 12 ?? 'morning' !! 'day'};
say &foo.signature;

# OUTPUT: Good day Paul!
          (:&greeting!, :$name!)

It’s really nice how interpolation and placeholders work together here. I have reported the ENODOC.

Even after years and years of being a Raku beginner, I still find new stuff when digging deep enough. Maybe it’s a good thing that we don’t have a Raku book. It would surely be backbreaking.

Categories: Raku